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

#include "chrome/installer/util/install_util.h"

#include <shellapi.h>
#include <shlobj.h>

#include <algorithm>

#include "base/file_util.h"
#include "base/logging.h"
#include "base/registry.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "base/win_util.h"

#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/work_item_list.h"

bool InstallUtil::ExecuteExeAsAdmin(const std::wstring& exe,
                                    const std::wstring& params,
                                    DWORD* exit_code) {
  SHELLEXECUTEINFO info = {0};
  info.cbSize = sizeof(SHELLEXECUTEINFO);
  info.fMask = SEE_MASK_NOCLOSEPROCESS;
  info.lpVerb = L"runas";
  info.lpFile = exe.c_str();
  info.lpParameters = params.c_str();
  info.nShow = SW_SHOW;
  if (::ShellExecuteEx(&info) == FALSE)
    return false;

  ::WaitForSingleObject(info.hProcess, INFINITE);
  DWORD ret_val = 0;
  if (!::GetExitCodeProcess(info.hProcess, &ret_val))
    return false;

  if (exit_code)
    *exit_code = ret_val;
  return true;
}

std::wstring InstallUtil::GetChromeUninstallCmd(bool system_install) {
  HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  RegKey key(root, dist->GetUninstallRegPath().c_str());
  std::wstring uninstall_cmd;
  key.ReadValue(installer_util::kUninstallStringField, &uninstall_cmd);
  return uninstall_cmd;
}

installer::Version* InstallUtil::GetChromeVersion(bool system_install) {
  RegKey key;
  std::wstring version_str;

  HKEY reg_root = (system_install) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  if (!key.Open(reg_root, dist->GetVersionKey().c_str(), KEY_READ) ||
      !key.ReadValue(google_update::kRegVersionField, &version_str)) {
    LOG(INFO) << "No existing Chrome install found.";
    key.Close();
    return NULL;
  }
  key.Close();
  LOG(INFO) << "Existing Chrome version found " << version_str;
  return installer::Version::GetVersionFromString(version_str);
}

bool InstallUtil::IsOSSupported() {
  int major, minor;
  win_util::WinVersion version = win_util::GetWinVersion();
  win_util::GetServicePackLevel(&major, &minor);

  // We do not support Win2K or older, or XP without service pack 1.
  LOG(INFO) << "Windows Version: " << version
            << ", Service Pack: " << major << "." << minor;
  if ((version > win_util::WINVERSION_XP) ||
      (version == win_util::WINVERSION_XP && major >= 1)) {
    return true;
  }
  return false;
}

void InstallUtil::WriteInstallerResult(bool system_install,
                                       installer_util::InstallStatus status,
                                       int string_resource_id,
                                       const std::wstring* const launch_cmd) {
  HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring key = dist->GetStateKey();
  int installer_result = (dist->GetInstallReturnCode(status) == 0) ? 0 : 1;
  scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
  install_list->AddCreateRegKeyWorkItem(root, key);
  install_list->AddSetRegValueWorkItem(root, key, L"InstallerResult",
                                       installer_result, true);
  install_list->AddSetRegValueWorkItem(root, key, L"InstallerError",
                                       status, true);
  if (string_resource_id != 0) {
    std::wstring msg = installer_util::GetLocalizedString(string_resource_id);
    install_list->AddSetRegValueWorkItem(root, key, L"InstallerResultUIString",
                                         msg, true);
  }
  // TODO(rahulk) verify that the absence of InstallerSuccessLaunchCmdLine
  // for non-system installs does not break the gcapi.dll.
  if ((launch_cmd != NULL) && system_install) {
    install_list->AddSetRegValueWorkItem(root, key,
                                         L"InstallerSuccessLaunchCmdLine",
                                         *launch_cmd, true);
  }
  if (!install_list->Do())
    LOG(ERROR) << "Failed to record installer error information in registry.";
}

bool InstallUtil::IsPerUserInstall(const wchar_t* const exe_path) {
  wchar_t program_files_path[MAX_PATH] = {0};
  if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
                                SHGFP_TYPE_CURRENT, program_files_path))) {
    return !StartsWith(exe_path, program_files_path, false);
  } else {
    NOTREACHED();
  }
  return true;
}

bool InstallUtil::BuildDLLRegistrationList(const std::wstring& install_path,
                                           const wchar_t** const dll_names,
                                           int dll_names_count,
                                           bool do_register,
                                           WorkItemList* registration_list) {
  DCHECK(NULL != registration_list);
  bool success = true;
  for (int i = 0; i < dll_names_count; i++) {
    std::wstring dll_file_path(install_path);
    file_util::AppendToPath(&dll_file_path, dll_names[i]);
    success = registration_list->AddSelfRegWorkItem(dll_file_path,
        do_register) && success;
  }
  return (dll_names_count > 0) && success;
}
<commit_msg>Roll back double launch of chrome fix<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// See the corresponding header file for description of the functions in this
// file.

#include "chrome/installer/util/install_util.h"

#include <shellapi.h>
#include <shlobj.h>

#include <algorithm>

#include "base/file_util.h"
#include "base/logging.h"
#include "base/registry.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "base/win_util.h"

#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/work_item_list.h"

bool InstallUtil::ExecuteExeAsAdmin(const std::wstring& exe,
                                    const std::wstring& params,
                                    DWORD* exit_code) {
  SHELLEXECUTEINFO info = {0};
  info.cbSize = sizeof(SHELLEXECUTEINFO);
  info.fMask = SEE_MASK_NOCLOSEPROCESS;
  info.lpVerb = L"runas";
  info.lpFile = exe.c_str();
  info.lpParameters = params.c_str();
  info.nShow = SW_SHOW;
  if (::ShellExecuteEx(&info) == FALSE)
    return false;

  ::WaitForSingleObject(info.hProcess, INFINITE);
  DWORD ret_val = 0;
  if (!::GetExitCodeProcess(info.hProcess, &ret_val))
    return false;

  if (exit_code)
    *exit_code = ret_val;
  return true;
}

std::wstring InstallUtil::GetChromeUninstallCmd(bool system_install) {
  HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  RegKey key(root, dist->GetUninstallRegPath().c_str());
  std::wstring uninstall_cmd;
  key.ReadValue(installer_util::kUninstallStringField, &uninstall_cmd);
  return uninstall_cmd;
}

installer::Version* InstallUtil::GetChromeVersion(bool system_install) {
  RegKey key;
  std::wstring version_str;

  HKEY reg_root = (system_install) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  if (!key.Open(reg_root, dist->GetVersionKey().c_str(), KEY_READ) ||
      !key.ReadValue(google_update::kRegVersionField, &version_str)) {
    LOG(INFO) << "No existing Chrome install found.";
    key.Close();
    return NULL;
  }
  key.Close();
  LOG(INFO) << "Existing Chrome version found " << version_str;
  return installer::Version::GetVersionFromString(version_str);
}

bool InstallUtil::IsOSSupported() {
  int major, minor;
  win_util::WinVersion version = win_util::GetWinVersion();
  win_util::GetServicePackLevel(&major, &minor);

  // We do not support Win2K or older, or XP without service pack 1.
  LOG(INFO) << "Windows Version: " << version
            << ", Service Pack: " << major << "." << minor;
  if ((version > win_util::WINVERSION_XP) ||
      (version == win_util::WINVERSION_XP && major >= 1)) {
    return true;
  }
  return false;
}

void InstallUtil::WriteInstallerResult(bool system_install,
                                       installer_util::InstallStatus status,
                                       int string_resource_id,
                                       const std::wstring* const launch_cmd) {
  HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring key = dist->GetStateKey();
  int installer_result = (dist->GetInstallReturnCode(status) == 0) ? 0 : 1;
  scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
  install_list->AddCreateRegKeyWorkItem(root, key);
  install_list->AddSetRegValueWorkItem(root, key, L"InstallerResult",
                                       installer_result, true);
  install_list->AddSetRegValueWorkItem(root, key, L"InstallerError",
                                       status, true);
  if (string_resource_id != 0) {
    std::wstring msg = installer_util::GetLocalizedString(string_resource_id);
    install_list->AddSetRegValueWorkItem(root, key, L"InstallerResultUIString",
                                         msg, true);
  }
  if (launch_cmd != NULL) {
    install_list->AddSetRegValueWorkItem(root, key,
                                         L"InstallerSuccessLaunchCmdLine",
                                         *launch_cmd, true);
  }
  if (!install_list->Do())
    LOG(ERROR) << "Failed to record installer error information in registry.";
}

bool InstallUtil::IsPerUserInstall(const wchar_t* const exe_path) {
  wchar_t program_files_path[MAX_PATH] = {0};
  if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
                                SHGFP_TYPE_CURRENT, program_files_path))) {
    return !StartsWith(exe_path, program_files_path, false);
  } else {
    NOTREACHED();
  }
  return true;
}

bool InstallUtil::BuildDLLRegistrationList(const std::wstring& install_path,
                                           const wchar_t** const dll_names,
                                           int dll_names_count,
                                           bool do_register,
                                           WorkItemList* registration_list) {
  DCHECK(NULL != registration_list);
  bool success = true;
  for (int i = 0; i < dll_names_count; i++) {
    std::wstring dll_file_path(install_path);
    file_util::AppendToPath(&dll_file_path, dll_names[i]);
    success = registration_list->AddSelfRegWorkItem(dll_file_path,
        do_register) && success;
  }
  return (dll_names_count > 0) && success;
}
<|endoftext|>


<commit_before>#pragma once
#ifndef STATICDELEGATE_HPP
# define STATICDELEGATE_HPP

#include <cassert>

#include <cstdlib>

#include <atomic>

#include <limits>

#include <memory>

#include <new>

#include <thread>

#include <type_traits>

#include <utility>

#include "lightptr.hpp"

namespace
{
  template <typename T, typename A = unsigned char>
  struct static_store
  {
    static constexpr auto const max_instances =
      ::std::numeric_limits<unsigned char>::digits * sizeof(A);

    static void cleanup() { delete [] store_; }

#ifdef __GNUC__
    template <typename U>
    static int ffz(U const v)
    {
      return __builtin_ctzll(~v);
    }
#elif _MSC_VER && !__INTEL_COMPILER
    template <typename U>
    static int ffz(U const v)
    {
      return ::std::numeric_limits<unsigned char>::digits * sizeof(v) -
        __lzcnt64(v & -v);
    }
#elif __INTEL_COMPILER
    template <typename U>
    static int ffz(U const v)
    {
      return _bit_scan_forward(~v);
    }
#else
    template <typename U>
    static int ffz(U v)
    {
      decltype(ffz()) b{};

      for (; (v & 1); ++b)
      {
        v >>= 1;
      }

      return b;
    }
#endif

    static ::std::atomic_flag lock_;

    static A memory_map_;

    static typename ::std::aligned_storage<sizeof(T),
      alignof(T)>::type* store_;
  };

  template <typename T, typename A>
  ::std::atomic_flag static_store<T, A>::lock_;

  template <typename T, typename A>
  A static_store<T, A>::memory_map_;

  template <typename T, typename A>
  typename ::std::aligned_storage<sizeof(T), alignof(T)>::type*
    static_store<T, A>::store_{(::std::atexit(static_store<T, A>::cleanup),
      new typename ::std::aligned_storage<sizeof(T),
        alignof(T)>::type[static_store<T, A>::max_instances])};

  template <typename T, typename ...A>
  inline T* static_new(A&& ...args)
  {
    using static_store = static_store<T>;

    while (static_store::lock_.test_and_set(::std::memory_order_acquire))
    {
      ::std::this_thread::yield();
    }

    if (::std::numeric_limits<decltype(static_store::memory_map_)>::max() ==
      static_store::memory_map_)
    {
      return static_cast<T*>(::operator new(sizeof(T)));
    }
    else
    {
      auto const i(static_store::ffz(static_store::memory_map_));

      auto p(new (&static_store::store_[i]) T(::std::forward<A>(args)...));

      static_store::memory_map_ |= 1ull << i;

      static_store::lock_.clear(::std::memory_order_release);

      return p;
    }
  }

  template <typename T>
  inline void static_delete(T* const p)
  {
    using static_store = static_store<T>;

    if ((static_cast<char*>(static_cast<void*>(p)) >=
      static_cast<char*>(static_cast<void*>(static_store::store_))) &&
      (static_cast<char*>(static_cast<void*>(static_store::store_)) +
        static_store::max_instances * sizeof(T) >
      static_cast<char*>(static_cast<void*>(p))))
    {
      auto const i(p - static_cast<T*>(static_cast<void*>(
        static_store::store_)));
      //assert(!as_const(static_store::memory_map_)[i]);

      while (static_store::lock_.test_and_set(::std::memory_order_acquire))
      {
        ::std::this_thread::yield();
      }

      static_store::memory_map_ &= ~(1ull << i);

      static_cast<T*>(static_cast<void*>(&static_store::store_[i]))->~T();

      static_store::lock_.clear(::std::memory_order_release);
    }
    else
    {
      ::operator delete(p);
    }
  }
}

template <typename T> class delegate;

template<class R, class ...A>
class delegate<R (A...)>
{
  using stub_ptr_type = R (*)(void*, A&&...);

  delegate(void* const o, stub_ptr_type const m) noexcept
    : object_ptr_(o),
      stub_ptr_(m)
  {
  }

public:
  delegate() = default;

  delegate(delegate const&) = default;

  delegate(delegate&&) = default;

  delegate(::std::nullptr_t const) noexcept : delegate() { }

  template <class C, typename =
    typename ::std::enable_if<::std::is_class<C>{}>::type>
  explicit delegate(C const* const o) noexcept :
    object_ptr_(const_cast<C*>(o))
  {
  }

  template <class C, typename =
    typename ::std::enable_if<::std::is_class<C>{}>::type>
  explicit delegate(C const& o) noexcept :
    object_ptr_(const_cast<C*>(&o))
  {
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...))
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C& object, R (C::* const method_ptr)(A...))
  {
    *this = from(object, method_ptr);
  }

  template <class C>
  delegate(C const& object, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object, method_ptr);
  }

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<delegate, typename ::std::decay<T>::type>{}
    >::type
  >
  delegate(T&& f) :
    store_(static_new<typename ::std::decay<T>::type>(::std::forward<T>(f)),
      functor_deleter<typename ::std::decay<T>::type>)
  {
    using functor_type = typename ::std::decay<T>::type;

    object_ptr_ = store_.get();

    stub_ptr_ = functor_stub<functor_type>;
  }

  delegate& operator=(delegate const&) = default;

  delegate& operator=(delegate&& rhs) = default;

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...))
  {
    return *this = from(static_cast<C*>(object_ptr_), rhs);
  }

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...) const)
  {
    return *this = from(static_cast<C const*>(object_ptr_), rhs);
  }

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<delegate, typename ::std::decay<T>::type>{}
    >::type
  >
  delegate& operator=(T&& f)
  {
    using functor_type = typename ::std::decay<T>::type;

    store_.reset(static_new<functor_type>(::std::forward<T>(f)),
      functor_deleter<functor_type>);

    object_ptr_ = store_.get();

    stub_ptr_ = functor_stub<functor_type>;

    return *this;
  }

  template <R (* const function_ptr)(A...)>
  static delegate from() noexcept
  {
    return { nullptr, function_stub<function_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C* const object_ptr) noexcept
  {
    return { object_ptr, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const* const object_ptr) noexcept
  {
    return { const_cast<C*>(object_ptr), const_method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C& object) noexcept
  {
    return { &object, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const& object) noexcept
  {
    return { const_cast<C*>(&object), const_method_stub<C, method_ptr> };
  }

  template <typename T>
  static delegate from(T&& f)
  {
    return ::std::forward<T>(f);
  }

  static delegate from(R (* const function_ptr)(A...))
  {
    return function_ptr;
  }

  template <class C>
  using member_pair =
    ::std::pair<C* const, R (C::* const)(A...)>;

  template <class C>
  using const_member_pair =
    ::std::pair<C const* const, R (C::* const)(A...) const>;

  template <class C>
  static delegate from(C* const object_ptr,
    R (C::* const method_ptr)(A...))
  {
    return member_pair<C>(object_ptr, method_ptr);
  }

  template <class C>
  static delegate from(C const* const object_ptr,
    R (C::* const method_ptr)(A...) const)
  {
    return const_member_pair<C>(object_ptr, method_ptr);
  }

  template <class C>
  static delegate from(C& object, R (C::* const method_ptr)(A...))
  {
    return member_pair<C>(&object, method_ptr);
  }

  template <class C>
  static delegate from(C const& object,
    R (C::* const method_ptr)(A...) const)
  {
    return const_member_pair<C>(&object, method_ptr);
  }

  void reset() { stub_ptr_ = nullptr; store_.reset(); }

  void reset_stub() noexcept { stub_ptr_ = nullptr; }

  void swap(delegate& other) noexcept { ::std::swap(*this, other); }

  bool operator==(delegate const& rhs) const noexcept
  {
    return (object_ptr_ == rhs.object_ptr_) && (stub_ptr_ == rhs.stub_ptr_);
  }

  bool operator!=(delegate const& rhs) const noexcept
  {
    return !operator==(rhs);
  }

  bool operator<(delegate const& rhs) const noexcept
  {
    return (object_ptr_ < rhs.object_ptr_) ||
      ((object_ptr_ == rhs.object_ptr_) && (stub_ptr_ < rhs.stub_ptr_));
  }

  bool operator==(::std::nullptr_t const) const noexcept
  {
    return !stub_ptr_;
  }

  bool operator!=(::std::nullptr_t const) const noexcept
  {
    return stub_ptr_;
  }

  explicit operator bool() const noexcept { return stub_ptr_; }

  R operator()(A... args) const
  {
//  assert(stub_ptr);
    return stub_ptr_(object_ptr_, ::std::forward<A>(args)...);
  }

private:
  friend class ::std::hash<delegate>;

  void* object_ptr_;
  stub_ptr_type stub_ptr_{};

  light_ptr<void> store_;

  template <class T>
  static void functor_deleter(void* const p)
  {
    static_delete(static_cast<T*>(p));
  }

  template <R (*function_ptr)(A...)>
  static R function_stub(void* const, A&&... args)
  {
    return function_ptr(::std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...)>
  static R method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C*>(object_ptr)->*method_ptr)(
      ::std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...) const>
  static R const_method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C const*>(object_ptr)->*method_ptr)(
      ::std::forward<A>(args)...);
  }

  template <typename>
  struct is_member_pair : std::false_type { };

  template <class C>
  struct is_member_pair<::std::pair<C* const,
    R (C::* const)(A...)> > : std::true_type
  {
  };

  template <typename>
  struct is_const_member_pair : std::false_type { };

  template <class C>
  struct is_const_member_pair<::std::pair<C const* const,
    R (C::* const)(A...) const> > : std::true_type
  {
  };

  template <typename T>
  static typename ::std::enable_if<
    !(is_member_pair<T>{} ||
    is_const_member_pair<T>{}),
    R
  >::type
  functor_stub(void* const object_ptr, A&&... args)
  {
    return (*static_cast<T*>(object_ptr))(::std::forward<A>(args)...);
  }

  template <typename T>
  static typename ::std::enable_if<
    is_member_pair<T>{} ||
    is_const_member_pair<T>{},
    R
  >::type
  functor_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<T*>(object_ptr)->first->*
      static_cast<T*>(object_ptr)->second)(::std::forward<A>(args)...);
  }
};

namespace std
{
  template <typename R, typename ...A>
  struct hash<delegate<R (A...)> >
  {
    size_t operator()(delegate<R (A...)> const& d) const noexcept
    {
      auto const seed(hash<void*>()(d.object_ptr_));

      return hash<typename delegate<R (A...)>::stub_ptr_type>()(d.stub_ptr_) +
        0x9e3779b9 + (seed << 6) + (seed >> 2);
    }
  };
}

#endif // STATICDELEGATE_HPP
<commit_msg>strips<commit_after>#pragma once
#ifndef STATICDELEGATE_HPP
# define STATICDELEGATE_HPP

#include <cassert>

#include <cstdlib>

#include <atomic>

#include <limits>

#include <memory>

#include <new>

#include <thread>

#include <type_traits>

#include <utility>

#include "lightptr.hpp"

namespace
{
  template <typename T, typename A = unsigned char>
  struct static_store
  {
    static_assert(::std::is_unsigned<A>{}, "A has to be unsigned");

    static constexpr auto const max_instances =
      ::std::numeric_limits<unsigned char>::digits * sizeof(A);

    static void cleanup() { delete [] store_; }

#ifdef __GNUC__
    template <typename U>
    static int ffz(U const v)
    {
      return __builtin_ctzll(~v);
    }
#elif _MSC_VER && !__INTEL_COMPILER
    template <typename U>
    static int ffz(U const v)
    {
      return ::std::numeric_limits<unsigned char>::digits * sizeof(v) -
        __lzcnt64(v & -v);
    }
#elif __INTEL_COMPILER
    template <typename U>
    static int ffz(U const v)
    {
      return _bit_scan_forward(~v);
    }
#else
    template <typename U>
    static int ffz(U v)
    {
      decltype(ffz()) b{};

      for (; (v & 1); ++b)
      {
        v >>= 1;
      }

      return b;
    }
#endif

    static ::std::atomic_flag lock_;

    static A memory_map_;

    static typename ::std::aligned_storage<sizeof(T),
      alignof(T)>::type* store_;
  };

  template <typename T, typename A>
  ::std::atomic_flag static_store<T, A>::lock_;

  template <typename T, typename A>
  A static_store<T, A>::memory_map_;

  template <typename T, typename A>
  typename ::std::aligned_storage<sizeof(T), alignof(T)>::type*
    static_store<T, A>::store_{(::std::atexit(static_store<T, A>::cleanup),
      new typename ::std::aligned_storage<sizeof(T),
        alignof(T)>::type[static_store<T, A>::max_instances])};

  template <typename T, typename ...A>
  inline T* static_new(A&& ...args)
  {
    using static_store = static_store<T>;

    while (static_store::lock_.test_and_set(::std::memory_order_acquire))
    {
      ::std::this_thread::yield();
    }

    if (::std::numeric_limits<decltype(static_store::memory_map_)>::max() ==
      static_store::memory_map_)
    {
      return static_cast<T*>(::operator new(sizeof(T)));
    }
    else
    {
      auto const i(static_store::ffz(static_store::memory_map_));

      auto p(new (&static_store::store_[i]) T(::std::forward<A>(args)...));

      static_store::memory_map_ |= 1ull << i;

      static_store::lock_.clear(::std::memory_order_release);

      return p;
    }
  }

  template <typename T>
  inline void static_delete(T* const p)
  {
    using static_store = static_store<T>;

    if ((static_cast<char*>(static_cast<void*>(p)) >=
      static_cast<char*>(static_cast<void*>(static_store::store_))) &&
      (static_cast<char*>(static_cast<void*>(static_store::store_)) +
        static_store::max_instances * sizeof(T) >
      static_cast<char*>(static_cast<void*>(p))))
    {
      auto const i(p - static_cast<T*>(static_cast<void*>(
        static_store::store_)));
      //assert(!as_const(static_store::memory_map_)[i]);

      while (static_store::lock_.test_and_set(::std::memory_order_acquire))
      {
        ::std::this_thread::yield();
      }

      static_store::memory_map_ &= ~(1ull << i);

      static_cast<T*>(static_cast<void*>(&static_store::store_[i]))->~T();

      static_store::lock_.clear(::std::memory_order_release);
    }
    else
    {
      ::operator delete(p);
    }
  }
}

template <typename T> class delegate;

template<class R, class ...A>
class delegate<R (A...)>
{
  using stub_ptr_type = R (*)(void*, A&&...);

  delegate(void* const o, stub_ptr_type const m) noexcept
    : object_ptr_(o),
      stub_ptr_(m)
  {
  }

public:
  delegate() = default;

  delegate(delegate const&) = default;

  delegate(delegate&&) = default;

  delegate(::std::nullptr_t const) noexcept : delegate() { }

  template <class C, typename =
    typename ::std::enable_if<::std::is_class<C>{}>::type>
  explicit delegate(C const* const o) noexcept :
    object_ptr_(const_cast<C*>(o))
  {
  }

  template <class C, typename =
    typename ::std::enable_if<::std::is_class<C>{}>::type>
  explicit delegate(C const& o) noexcept :
    object_ptr_(const_cast<C*>(&o))
  {
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...))
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C& object, R (C::* const method_ptr)(A...))
  {
    *this = from(object, method_ptr);
  }

  template <class C>
  delegate(C const& object, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object, method_ptr);
  }

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<delegate, typename ::std::decay<T>::type>{}
    >::type
  >
  delegate(T&& f) :
    store_(static_new<typename ::std::decay<T>::type>(::std::forward<T>(f)),
      functor_deleter<typename ::std::decay<T>::type>)
  {
    using functor_type = typename ::std::decay<T>::type;

    object_ptr_ = store_.get();

    stub_ptr_ = functor_stub<functor_type>;
  }

  delegate& operator=(delegate const&) = default;

  delegate& operator=(delegate&& rhs) = default;

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...))
  {
    return *this = from(static_cast<C*>(object_ptr_), rhs);
  }

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...) const)
  {
    return *this = from(static_cast<C const*>(object_ptr_), rhs);
  }

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<delegate, typename ::std::decay<T>::type>{}
    >::type
  >
  delegate& operator=(T&& f)
  {
    using functor_type = typename ::std::decay<T>::type;

    store_.reset(static_new<functor_type>(::std::forward<T>(f)),
      functor_deleter<functor_type>);

    object_ptr_ = store_.get();

    stub_ptr_ = functor_stub<functor_type>;

    return *this;
  }

  template <R (* const function_ptr)(A...)>
  static delegate from() noexcept
  {
    return { nullptr, function_stub<function_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C* const object_ptr) noexcept
  {
    return { object_ptr, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const* const object_ptr) noexcept
  {
    return { const_cast<C*>(object_ptr), const_method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C& object) noexcept
  {
    return { &object, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const& object) noexcept
  {
    return { const_cast<C*>(&object), const_method_stub<C, method_ptr> };
  }

  template <typename T>
  static delegate from(T&& f)
  {
    return ::std::forward<T>(f);
  }

  static delegate from(R (* const function_ptr)(A...))
  {
    return function_ptr;
  }

  template <class C>
  using member_pair =
    ::std::pair<C* const, R (C::* const)(A...)>;

  template <class C>
  using const_member_pair =
    ::std::pair<C const* const, R (C::* const)(A...) const>;

  template <class C>
  static delegate from(C* const object_ptr,
    R (C::* const method_ptr)(A...))
  {
    return member_pair<C>(object_ptr, method_ptr);
  }

  template <class C>
  static delegate from(C const* const object_ptr,
    R (C::* const method_ptr)(A...) const)
  {
    return const_member_pair<C>(object_ptr, method_ptr);
  }

  template <class C>
  static delegate from(C& object, R (C::* const method_ptr)(A...))
  {
    return member_pair<C>(&object, method_ptr);
  }

  template <class C>
  static delegate from(C const& object,
    R (C::* const method_ptr)(A...) const)
  {
    return const_member_pair<C>(&object, method_ptr);
  }

  void reset() { stub_ptr_ = nullptr; store_.reset(); }

  void reset_stub() noexcept { stub_ptr_ = nullptr; }

  void swap(delegate& other) noexcept { ::std::swap(*this, other); }

  bool operator==(delegate const& rhs) const noexcept
  {
    return (object_ptr_ == rhs.object_ptr_) && (stub_ptr_ == rhs.stub_ptr_);
  }

  bool operator!=(delegate const& rhs) const noexcept
  {
    return !operator==(rhs);
  }

  bool operator<(delegate const& rhs) const noexcept
  {
    return (object_ptr_ < rhs.object_ptr_) ||
      ((object_ptr_ == rhs.object_ptr_) && (stub_ptr_ < rhs.stub_ptr_));
  }

  bool operator==(::std::nullptr_t const) const noexcept
  {
    return !stub_ptr_;
  }

  bool operator!=(::std::nullptr_t const) const noexcept
  {
    return stub_ptr_;
  }

  explicit operator bool() const noexcept { return stub_ptr_; }

  R operator()(A... args) const
  {
//  assert(stub_ptr);
    return stub_ptr_(object_ptr_, ::std::forward<A>(args)...);
  }

private:
  friend class ::std::hash<delegate>;

  void* object_ptr_;
  stub_ptr_type stub_ptr_{};

  light_ptr<void> store_;

  template <class T>
  static void functor_deleter(void* const p)
  {
    static_delete(static_cast<T*>(p));
  }

  template <R (*function_ptr)(A...)>
  static R function_stub(void* const, A&&... args)
  {
    return function_ptr(::std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...)>
  static R method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C*>(object_ptr)->*method_ptr)(
      ::std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...) const>
  static R const_method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C const*>(object_ptr)->*method_ptr)(
      ::std::forward<A>(args)...);
  }

  template <typename>
  struct is_member_pair : std::false_type { };

  template <class C>
  struct is_member_pair<::std::pair<C* const,
    R (C::* const)(A...)> > : std::true_type
  {
  };

  template <typename>
  struct is_const_member_pair : std::false_type { };

  template <class C>
  struct is_const_member_pair<::std::pair<C const* const,
    R (C::* const)(A...) const> > : std::true_type
  {
  };

  template <typename T>
  static typename ::std::enable_if<
    !(is_member_pair<T>{} ||
    is_const_member_pair<T>{}),
    R
  >::type
  functor_stub(void* const object_ptr, A&&... args)
  {
    return (*static_cast<T*>(object_ptr))(::std::forward<A>(args)...);
  }

  template <typename T>
  static typename ::std::enable_if<
    is_member_pair<T>{} ||
    is_const_member_pair<T>{},
    R
  >::type
  functor_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<T*>(object_ptr)->first->*
      static_cast<T*>(object_ptr)->second)(::std::forward<A>(args)...);
  }
};

namespace std
{
  template <typename R, typename ...A>
  struct hash<delegate<R (A...)> >
  {
    size_t operator()(delegate<R (A...)> const& d) const noexcept
    {
      auto const seed(hash<void*>()(d.object_ptr_));

      return hash<typename delegate<R (A...)>::stub_ptr_type>()(d.stub_ptr_) +
        0x9e3779b9 + (seed << 6) + (seed >> 2);
    }
  };
}

#endif // STATICDELEGATE_HPP
<|endoftext|>


<commit_before>
# FIXME update to match proper spec, and include serialisation annotations
type mcd_request : record
  key : string

type mcd_reply : record
  key : string
  value : string

proc MCD : (type mcd_request/type mcd_reply client, [type mcd_request/type mcd_reply] backends)
  # NOTE (possibly shared) dictionaries are application-level primitives we supply.
  # FIXME specift what parameters to give? e.g., whether to randomise, and initial allocation.
  global cache : dictionary <string * string> := empty_dictionary

  # Any time we get something from a backend, cache it and forward it to the
  # client.
  backends => update_cache(cache) => client

  client => test_cache_or_pass_on(client, backends)

fun update_cache : (cache : ref dictionary <string * string>, response : type mcd_reply) -> (type mcd_reply)
  # NOTE relying on pass-by-reference of cache
  cache[response.key] := response
  response

fun test_cache_or_pass_on : (type mcd_request/type mcd_reply client, [type mcd_request/type mcd_reply] backend; request : type mcd_request) -> ()
  if cache[request.key] = None:
    # Work out which backend memcached to forward this request to, and send.
    request => backends[hash(request.key) mod len(backends)]
  else:
    cache[request.key] => client
<commit_msg>updated to use the new type;<commit_after>include "mc_type.cp"

proc MCD : (type mcd_request/type mcd_reply client, [type mcd_request/type mcd_reply] backends)
  # NOTE (possibly shared) dictionaries are application-level primitives we supply.
  # FIXME specift what parameters to give? e.g., whether to randomise, and initial allocation.
  global cache : dictionary <string * string> := empty_dictionary

  # Any time we get something from a backend, cache it and forward it to the
  # client.
  backends => update_cache(cache) => client

  client => test_cache_or_pass_on(client, backends)

fun update_cache : (cache : ref dictionary <string * string>, response : type mcd_reply) -> (type mcd_reply)
  # NOTE relying on pass-by-reference of cache
  cache[response.key] := response
  response

fun test_cache_or_pass_on : (type mcd_request/type mcd_reply client, [type mcd_request/type mcd_reply] backend; request : type mcd_request) -> ()
  if cache[request.key] = None:
    # Work out which backend memcached to forward this request to, and send.
    request => backends[hash(request.key) mod len(backends)]
  else:
    cache[request.key] => client
<|endoftext|>


<commit_before>/*
** Copyright 2014 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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 Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#ifndef BAM_CCB_CONFIGURATION_BOOL_EXPRESSION_HH
#  define CCB_BAM_CONFIGURATION_BOOL_EXPRESSION_HH

#  include <string>
#  include "com/centreon/broker/namespace.hh"

CCB_BEGIN()

namespace                   bam {
  namespace                 configuration {
    /**
     *@class bool_expression bool_expression.hh  "com/centreon/broker/bam/configuration/bool_expression.h"
     *
     *@brief A pseudo-kpi triggered by a the value of a boolean expression.
     */
    class                   bool_expression {
    public:
                            bool_expression(
                              unsigned int id = 0,
                              double impact = 0.0,
                              std::string const& expression = "",
                              bool impact_if = false,
                              bool state = false);
                            bool_expression(bool_expression const& right);
      bool_expression&      operator=(bool_expression const& right);
                            ~bool_expression();

      unsigned int          get_id() const;
      double                get_impact() const;
      std::string const&    get_expression() const;
      bool                  get_impact_if() const;
      bool                  get_state() const;

      void                  set_impact(double d);
      void                  set_expression(std::string const& s);
      void                  set_impact_if(bool b);
      void                  set_state(bool s);

    private:
      unsigned int          _id;
      double                _impact;
      std::string           _expression;
      bool                  _impact_if;
      bool                  _state;
    };
  }
}

CCB_END()

#endif // !CCB_BAM_CONFIGURATION_BOOL_EXPRESSION_HH
<commit_msg>bam:conformance<commit_after>/*
** Copyright 2009-2014 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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 Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#ifndef BAM_CCB_CONFIGURATION_BOOL_EXPRESSION_HH
#  define CCB_BAM_CONFIGURATION_BOOL_EXPRESSION_HH

#  include <string>
#  include "com/centreon/broker/namespace.hh"

CCB_BEGIN()

namespace                 bam{
  namespace               configuration{
    /**
     *@class bool_expression bool_expression.hh  "com/centreon/broker/bam/configuration/bool_expression.h"
     *
     *@brief A pseudo-kpi triggered by a the value of a boolean expression.
     */
    class                   bool_expression {
    public:
                            bool_expression(
			      unsigned int id = 0,
			      double impact = 0.0,
			      std::string const& expression = "",
			      bool impact_if = false,
			      bool state = false);
                            bool_expression(bool_expression const& right);
      bool_expression&      operator=(bool_expression const& right);
                            ~bool_expression();

      unsigned int          get_id() const;
      double                get_impact() const;
      std::string const&    get_expression() const;
      bool                  get_impact_if() const;
      bool                  get_state() const;

      void                  set_impact(double d);
      void                  set_expression(std::string const& s);
      void                  set_impact_if(bool b);
      void                  set_state(bool s);

    private:
      unsigned int          _id;
      double                _impact;
      std::string           _expression;
      bool                  _impact_if;
      bool                  _state;
    };
  }
}

CCB_END()

#endif // !CCB_BAM_CONFIGURATION_BOOL_EXPRESSION_HH
<|endoftext|>


<commit_before>#ifndef AMGCL_IO_BINARY_HPP
#define AMGCL_IO_BINARY_HPP

/*
The MIT License

Copyright (c) 2012-2019 Denis Demidov <dennis.demidov@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
 * \file   amgcl/io/binary.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  Convenience functions for binary file I/O.
 */

#include <vector>
#include <string>
#include <fstream>

#include <amgcl/util.hpp>

namespace amgcl {
namespace io {

/// Read single value from a binary file.
template <class T>
bool read(std::ifstream &f, T &val) {
    return static_cast<bool>(f.read((char*)&val, sizeof(T)));
}

/// Read vector from a binary file.
template <class T>
bool read(std::ifstream &f, std::vector<T> &vec) {
    return static_cast<bool>(f.read((char*)&vec[0], sizeof(T) * vec.size()));
}

/// Get CRS matrix size a binary file.
template <typename IndexType>
IndexType crs_size(const std::string &fname) {
    std::ifstream f(fname.c_str(), std::ios::binary);
    IndexType n;

    precondition(f, "Failed to open matrix file");
    precondition(read(f, n), "File I/O error");

    return n;
}

/// Read CRS matrix from a binary file.
template <typename SizeT, typename Ptr, typename Col, typename Val>
void read_crs(
        const std::string &fname,
        SizeT &n,
        std::vector<Ptr> &ptr,
        std::vector<Col> &col,
        std::vector<Val> &val,
        ptrdiff_t row_beg = -1,
        ptrdiff_t row_end = -1
        )
{
    std::ifstream f(fname.c_str(), std::ios::binary);
    precondition(f, "Failed to open matrix file");

    precondition(read(f, n), "File I/O error");

    if (row_beg < 0) row_beg = 0;
    if (row_end < 0) row_end = n;

    precondition(row_beg >= 0 && row_end <= static_cast<ptrdiff_t>(n),
            "Wrong subset of rows is requested");

    ptrdiff_t chunk = row_end - row_beg;

    ptr.resize(chunk + 1);

    size_t ptr_beg = sizeof(SizeT);
    f.seekg(ptr_beg + row_beg * sizeof(Ptr));
    precondition(read(f, ptr), "File I/O error");

    size_t nnz;
    f.seekg(ptr_beg + n * sizeof(Ptr));
    precondition(read(f, nnz), "File I/O error");

    SizeT nnz_beg = ptr.front();
    if (nnz_beg) for(auto &p : ptr) p -= nnz_beg;

    col.resize(ptr.back());
    val.resize(ptr.back());

    size_t col_beg = ptr_beg + (n + 1) * sizeof(Ptr);
    f.seekg(col_beg + nnz_beg * sizeof(Col));
    precondition(read(f, col), "File I/O error");

    f.seekg(col_beg + nnz * sizeof(Col) + nnz_beg * sizeof(Val));
    precondition(read(f, val), "File I/O error");
}

template <typename SizeT, typename Val>
void read_dense(const std::string &fname,
        SizeT &n, SizeT &m, std::vector<Val> &v,
        ptrdiff_t row_beg = -1, ptrdiff_t row_end = -1)
{
    std::ifstream f(fname.c_str(), std::ios::binary);
    precondition(f, "Failed to open matrix file");

    precondition(read(f, n), "File I/O error");
    precondition(read(f, m), "File I/O error");

    if (row_beg < 0) row_beg = 0;
    if (row_end < 0) row_end = n;

    precondition(row_beg >= 0 && row_end <= static_cast<ptrdiff_t>(n),
            "Wrong subset of rows is requested");

    ptrdiff_t chunk = row_end - row_beg;

    v.resize(chunk * m);

    f.seekg(2 * sizeof(SizeT) + row_beg * m * sizeof(Val));
    precondition(read(f, v), "File I/O error");
}

/// Write single value to a binary file.
template <class T>
bool write(std::ofstream &f, const T &val) {
    return static_cast<bool>(f.write((char*)&val, sizeof(T)));
}

/// Write vector to a binary file.
template <class T>
bool write(std::ofstream &f, const std::vector<T> &vec) {
    return static_cast<bool>(f.write((char*)&vec[0], sizeof(T) * vec.size()));
}

} // namespace io
} // namespace amgcl

#endif
<commit_msg>Sort matrix rows when reading binary file<commit_after>#ifndef AMGCL_IO_BINARY_HPP
#define AMGCL_IO_BINARY_HPP

/*
The MIT License

Copyright (c) 2012-2019 Denis Demidov <dennis.demidov@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
 * \file   amgcl/io/binary.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  Convenience functions for binary file I/O.
 */

#include <vector>
#include <string>
#include <fstream>

#include <amgcl/util.hpp>

namespace amgcl {
namespace io {

/// Read single value from a binary file.
template <class T>
bool read(std::ifstream &f, T &val) {
    return static_cast<bool>(f.read((char*)&val, sizeof(T)));
}

/// Read vector from a binary file.
template <class T>
bool read(std::ifstream &f, std::vector<T> &vec) {
    return static_cast<bool>(f.read((char*)&vec[0], sizeof(T) * vec.size()));
}

/// Get CRS matrix size a binary file.
template <typename IndexType>
IndexType crs_size(const std::string &fname) {
    std::ifstream f(fname.c_str(), std::ios::binary);
    IndexType n;

    precondition(f, "Failed to open matrix file");
    precondition(read(f, n), "File I/O error");

    return n;
}

/// Read CRS matrix from a binary file.
template <typename SizeT, typename Ptr, typename Col, typename Val>
void read_crs(
        const std::string &fname,
        SizeT &n,
        std::vector<Ptr> &ptr,
        std::vector<Col> &col,
        std::vector<Val> &val,
        ptrdiff_t row_beg = -1,
        ptrdiff_t row_end = -1
        )
{
    std::ifstream f(fname.c_str(), std::ios::binary);
    precondition(f, "Failed to open matrix file");

    precondition(read(f, n), "File I/O error");

    if (row_beg < 0) row_beg = 0;
    if (row_end < 0) row_end = n;

    precondition(row_beg >= 0 && row_end <= static_cast<ptrdiff_t>(n),
            "Wrong subset of rows is requested");

    ptrdiff_t chunk = row_end - row_beg;

    ptr.resize(chunk + 1);

    size_t ptr_beg = sizeof(SizeT);
    f.seekg(ptr_beg + row_beg * sizeof(Ptr));
    precondition(read(f, ptr), "File I/O error");

    size_t nnz;
    f.seekg(ptr_beg + n * sizeof(Ptr));
    precondition(read(f, nnz), "File I/O error");

    SizeT nnz_beg = ptr.front();
    if (nnz_beg) for(auto &p : ptr) p -= nnz_beg;

    col.resize(ptr.back());
    val.resize(ptr.back());

    size_t col_beg = ptr_beg + (n + 1) * sizeof(Ptr);
    f.seekg(col_beg + nnz_beg * sizeof(Col));
    precondition(read(f, col), "File I/O error");

    f.seekg(col_beg + nnz * sizeof(Col) + nnz_beg * sizeof(Val));
    precondition(read(f, val), "File I/O error");

#pragma omp parallel for
    for(ptrdiff_t i = 0; i < chunk; ++i) {
        Ptr beg = ptr[i];
        Ptr end = ptr[i + 1];
        amgcl::detail::sort_row(&col[beg], &val[beg], end - beg);
    }
}

template <typename SizeT, typename Val>
void read_dense(const std::string &fname,
        SizeT &n, SizeT &m, std::vector<Val> &v,
        ptrdiff_t row_beg = -1, ptrdiff_t row_end = -1)
{
    std::ifstream f(fname.c_str(), std::ios::binary);
    precondition(f, "Failed to open matrix file");

    precondition(read(f, n), "File I/O error");
    precondition(read(f, m), "File I/O error");

    if (row_beg < 0) row_beg = 0;
    if (row_end < 0) row_end = n;

    precondition(row_beg >= 0 && row_end <= static_cast<ptrdiff_t>(n),
            "Wrong subset of rows is requested");

    ptrdiff_t chunk = row_end - row_beg;

    v.resize(chunk * m);

    f.seekg(2 * sizeof(SizeT) + row_beg * m * sizeof(Val));
    precondition(read(f, v), "File I/O error");
}

/// Write single value to a binary file.
template <class T>
bool write(std::ofstream &f, const T &val) {
    return static_cast<bool>(f.write((char*)&val, sizeof(T)));
}

/// Write vector to a binary file.
template <class T>
bool write(std::ofstream &f, const std::vector<T> &vec) {
    return static_cast<bool>(f.write((char*)&vec[0], sizeof(T) * vec.size()));
}

} // namespace io
} // namespace amgcl

#endif
<|endoftext|>


<commit_before>/*********************************************************************
** Author: Zach Colbert
** Date:
** Description:
*********************************************************************/

#include <iostream>
#include <fstream>
#include <string>

using std::cout;
using std::cin;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::string;

// The main function
int main()
{
    // Code goes here
    return 0;
}
<commit_msg>Updated for assignments with no main method<commit_after>/*********************************************************************
** Author: Zach Colbert
** Date:
** Description:
*********************************************************************/

/*********************************************************************
Pre-Processing
*********************************************************************/
// This section is for pre-processor objects that are needed for actual code (not for the testing and development)

/*********************************************************************
End Pre-Processing
*********************************************************************/

/*********************************************************************
Testing -- MUST BE REMOVED OR COMMENTED BEFORE SUBMISSION
*********************************************************************/
// For testing -- move the pre-processing objects needed for the actual code up to the Pre-Processing section
#include <iostream>
#include <fstream>
#include <string>

using std::cout;
using std::cin;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::string;

// Function prototype

int main()
{
    // Testing and development code goes here
    // Don't write anything important in this section because it's going away!

    return 0;
}
/*********************************************************************
End Testing
*********************************************************************/

// Start defining actual functions here
void myFunction()
{
    // Actual code goes here.

    return void;
}<|endoftext|>


<commit_before>#include <ruby.h>
#include "hstcpcli.hpp"

typedef struct {
    dena::hstcpcli_i *ptr;
} HandlerSocket;

void parse_options(dena::config&, dena::socket_args&, VALUE);

VALUE hs_free(HandlerSocket* hs)
{
    // fprintf(stderr, "hs=%p\n", hs);
    if (hs) {
        // fprintf(stderr, "hs->ptr=%p\n", hs->ptr);
        if (hs->ptr) {
            hs->ptr->close();
            delete hs->ptr;
        }
        xfree(hs);
    }
}

VALUE hs_alloc(VALUE self)
{
    return Data_Wrap_Struct(self, NULL, hs_free, 0);
}

VALUE hs_initialize(VALUE self, VALUE options)
{
    HandlerSocket* hs;

    Data_Get_Struct(self, HandlerSocket, hs);
    // fprintf(stderr, "hs=%p\n", hs);
    if (!hs) {
        hs = (HandlerSocket*)xmalloc(sizeof(HandlerSocket));
        MEMZERO(hs, HandlerSocket, 1);
        DATA_PTR(self) = hs;
        // fprintf(stderr, "hs=%p\n", hs);
    }

    dena::config      conf;
    dena::socket_args args;
    parse_options(conf, args, options);

    dena::hstcpcli_ptr ptr = dena::hstcpcli_i::create(args);
    // fprintf(stderr, "ptr=%p\n", &ptr);
    hs->ptr = ptr.get();
    // fprintf(stderr, "hs->ptr=%p\n", hs->ptr);
    // fprintf(stderr, "ptr.get()=%p\n", ptr.get());
    ptr.release();

    return self;
}

VALUE hs_close(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    hs->ptr->close();
    return Qnil;
}

VALUE hs_reconnect(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    int retval = hs->ptr->reconnect();
    return INT2FIX(retval);
}

VALUE hs_stable_point(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    return hs->ptr->stable_point() ? Qtrue : Qfalse;
}

VALUE hs_error(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    VALUE val = Qnil;
    std::string error = hs->ptr->get_error();

    if (!error.empty()) {
        val = rb_str_new2(error.c_str());
    }
    return val;
}

VALUE hs_error_code(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    return INT2FIX(hs->ptr->get_error_code());
}

VALUE hs_open_index(VALUE self, VALUE id, VALUE db, VALUE table, VALUE index, VALUE fields)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    do {
        size_t pst_id = NUM2INT(id);
        ptr->request_buf_open_index(pst_id, StringValuePtr(db), StringValuePtr(table), StringValuePtr(index), StringValuePtr(fields));
        if (ptr->request_send() != 0) {
            break;
        }

        size_t nflds = 0;
        ptr->response_recv(nflds);
        const int e = ptr->get_error_code();
        // fprintf(stderr, "errcode=%d\n", e);
        if (e >= 0) {
            ptr->response_buf_remove();
        }
        // fprintf(stderr, "errcode=%d\n", ptr->get_error_code());
    } while(0);

    return INT2FIX(ptr->get_error_code());
}

VALUE hs_execute_single(int argc, VALUE *argv, VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    VALUE id, op, keys, limit, skip, modop, modvals;
    rb_scan_args(argc, argv, "52", &id, &op, &keys, &limit, &skip, &modop, &modvals);

    StringValue(op);
    Check_Type(keys, T_ARRAY);

    if (!NIL_P(modop)) {
        StringValue(modop);
        Check_Type(modvals, T_ARRAY);
    }

    dena::string_ref op_ref;
    std::vector<dena::string_ref> keyary;

    op_ref = dena::string_ref(RSTRING_PTR(op), RSTRING_LEN(op));

    keyary.reserve(RARRAY_LEN(keys));
    for (size_t i=0; i<RARRAY_LEN(keys); i++) {
        VALUE key = rb_ary_entry(keys, i);
        StringValuePtr(key);
        keyary.push_back(dena::string_ref(RSTRING_PTR(key), RSTRING_LEN(key)));
    }

    dena::string_ref modop_ref;
    std::vector<dena::string_ref> modary;

    if (!NIL_P(modop)) {
        modop_ref = dena::string_ref(RSTRING_PTR(modop), RSTRING_LEN(modop));

        modary.reserve(RARRAY_LEN(modvals));
        for (size_t i=0; i<RARRAY_LEN(modvals); i++) {
            VALUE key = rb_ary_entry(modvals, i);
            // StringValue(key);
            modary.push_back(dena::string_ref(RSTRING_PTR(key), RSTRING_LEN(key)));
        }
    }

    ptr->request_buf_exec_generic(NUM2INT(id),
                                  op_ref,
                                  &keyary[0], keyary.size(),
                                  NUM2INT(limit), NUM2INT(skip),
                                  modop_ref,
                                  &modary[0], modary.size());

    if (ptr->request_send() != 0) {
        return Qnil;
    }

    size_t nflds = 0;
    ptr->response_recv(nflds);
    // fprintf(stderr, "nflds=%zu\n", nflds);

    VALUE retval = rb_ary_new();

    const int e = ptr->get_error_code();
    // fprintf(stderr, "e=%d nflds=%zu\n", e, nflds);
    rb_ary_push(retval, FIX2INT(e));

    if (e != 0) {
        const std::string s = ptr->get_error();
        rb_ary_push(retval, rb_str_new2(s.c_str()));
    } else {
        VALUE arys, ary, val;

        arys = rb_ary_new();
        const dena::string_ref *row = 0;
        while ((row = ptr->get_next_row()) != 0) {
            // fprintf(stderr, "row=%p\n", row);
            ary = rb_ary_new2(nflds);
            for (size_t i = 0; i < nflds; ++i) {
                const dena::string_ref& v = row[i];
                // fprintf(stderr, "FLD %zu v=%s vbegin=%p\n", i, std::string(v.begin(), v.size()).c_str(), v.begin());
                if (v.begin() != 0) {
                    val = rb_str_new(v.begin(), v.size());
                    rb_ary_push(ary, val);
                } else {
                    rb_ary_push(ary, Qnil);
                }
            }
            rb_ary_push(arys, ary);
        }
        rb_ary_push(retval, arys);
    }

    if (e >= 0) {
      ptr->response_buf_remove();
    }

    return retval;
}

VALUE hs_execute_multi(int argc, VALUE *argv, VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    return Qnil;
}

VALUE hs_execute_find(int argc, VALUE *argv, VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    return Qnil;
}

VALUE hs_execute_update(int argc, VALUE *argv, VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    return Qnil;
}

VALUE hs_execute_delete(int argc, VALUE *argv, VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    return Qnil;
}

VALUE hs_execute_insert(int argc, VALUE *argv, VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    return Qnil;
}

void parse_options(dena::config& conf, dena::socket_args& args, VALUE options)
{
    VALUE val;

    Check_Type(options, T_HASH);

    val = rb_hash_aref(options, ID2SYM(rb_intern("host")));
    if(val != Qnil)
    {
        conf["host"] = std::string(StringValuePtr(val));
        // fprintf(stderr, "host=%s\n", conf["host"].c_str());
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("port")));
    if(val != Qnil)
    {
        conf["port"] = std::string(StringValuePtr(val));
        // fprintf(stderr, "port=%s\n", conf["port"].c_str());
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("timeout")));
    if(val != Qnil)
    {
        conf["timeout"] = std::string(StringValuePtr(val));
        // fprintf(stderr, "timeout=%s\n", conf["timeout"].c_str());
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("listen_backlog")));
    if(val != Qnil)
    {
        conf["listen_backlog"] = std::string(StringValuePtr(val));
        // fprintf(stderr, "listen_backlog=%s\n", conf["listen_backlog"].c_str());
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("sndbuf")));
    if(val != Qnil)
    {
        conf["sndbuf"] = std::string(StringValuePtr(val));
        // fprintf(stderr, "sndbuf=%s\n", conf["sndbuf"].c_str());
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("rcvbuf")));
    if(val != Qnil)
    {
        conf["rcvbuf"] = std::string(StringValuePtr(val));
        // fprintf(stderr, "rcvbuf=%s\n", conf["rcvbuf"].c_str());
    }

    args.set(conf);
}

extern "C" {
    void Init_handler_socket(void)
    {
        VALUE rb_cHandlerSocket = rb_define_class("HandlerSocket", rb_cObject);

        rb_define_alloc_func(rb_cHandlerSocket, hs_alloc);
        rb_define_private_method(rb_cHandlerSocket, "initialize", (VALUE(*)(...))hs_initialize, 1);

        rb_define_method(rb_cHandlerSocket, "close", (VALUE(*)(...))hs_close, 0);
        rb_define_method(rb_cHandlerSocket, "reconnect", (VALUE(*)(...))hs_reconnect, 0);
        rb_define_method(rb_cHandlerSocket, "stable_point", (VALUE(*)(...))hs_stable_point, 0);

        rb_define_method(rb_cHandlerSocket, "error", (VALUE(*)(...))hs_error, 0);
        rb_define_method(rb_cHandlerSocket, "error_code", (VALUE(*)(...))hs_error_code, 0);

        rb_define_method(rb_cHandlerSocket, "open_index", (VALUE(*)(...))hs_open_index, 5);
        rb_define_method(rb_cHandlerSocket, "execute_single", (VALUE(*)(...))hs_execute_single, -1);
        rb_define_method(rb_cHandlerSocket, "execute_multi", (VALUE(*)(...))hs_execute_multi, -1);
        rb_define_method(rb_cHandlerSocket, "execute_find", (VALUE(*)(...))hs_execute_find, -1);
        rb_define_method(rb_cHandlerSocket, "execute_update", (VALUE(*)(...))hs_execute_update, -1);
        rb_define_method(rb_cHandlerSocket, "execute_delete", (VALUE(*)(...))hs_execute_delete, -1);
        rb_define_method(rb_cHandlerSocket, "execute_insert", (VALUE(*)(...))hs_execute_insert, -1);
    }
}
<commit_msg>impl hs_execute_multi, hs_execute_update, hs_execute_delete and hs_execute_insert<commit_after>#include <ruby.h>
#include "hstcpcli.hpp"

typedef struct {
    dena::hstcpcli_i *ptr;
} HandlerSocket;

void parse_options(dena::config&, dena::socket_args&, VALUE);

VALUE hs_free(HandlerSocket* hs)
{
    // fprintf(stderr, "hs=%p\n", hs);
    if (hs) {
        // fprintf(stderr, "hs->ptr=%p\n", hs->ptr);
        if (hs->ptr) {
            hs->ptr->close();
            delete hs->ptr;
        }
        xfree(hs);
    }
}

VALUE hs_alloc(VALUE self)
{
    return Data_Wrap_Struct(self, NULL, hs_free, 0);
}

VALUE hs_initialize(VALUE self, VALUE options)
{
    HandlerSocket* hs;

    Data_Get_Struct(self, HandlerSocket, hs);
    // fprintf(stderr, "hs=%p\n", hs);
    if (!hs) {
        hs = (HandlerSocket*)xmalloc(sizeof(HandlerSocket));
        MEMZERO(hs, HandlerSocket, 1);
        DATA_PTR(self) = hs;
        // fprintf(stderr, "hs=%p\n", hs);
    }

    dena::config      conf;
    dena::socket_args args;
    parse_options(conf, args, options);

    dena::hstcpcli_ptr ptr = dena::hstcpcli_i::create(args);
    // fprintf(stderr, "ptr=%p\n", &ptr);
    hs->ptr = ptr.get();
    // fprintf(stderr, "hs->ptr=%p\n", hs->ptr);
    // fprintf(stderr, "ptr.get()=%p\n", ptr.get());
    ptr.release();

    return self;
}

VALUE hs_close(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    hs->ptr->close();
    return Qnil;
}

VALUE hs_reconnect(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    int retval = hs->ptr->reconnect();
    return INT2FIX(retval);
}

VALUE hs_stable_point(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    return hs->ptr->stable_point() ? Qtrue : Qfalse;
}

VALUE hs_error(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    VALUE val = Qnil;
    std::string error = hs->ptr->get_error();

    if (!error.empty()) {
        val = rb_str_new2(error.c_str());
    }
    return val;
}

VALUE hs_error_code(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    return INT2FIX(hs->ptr->get_error_code());
}

VALUE hs_open_index(VALUE self, VALUE id, VALUE db, VALUE table, VALUE index, VALUE fields)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    do {
        size_t pst_id = NUM2INT(id);
        ptr->request_buf_open_index(pst_id, StringValuePtr(db), StringValuePtr(table), StringValuePtr(index), StringValuePtr(fields));
        if (ptr->request_send() != 0) {
            break;
        }

        size_t nflds = 0;
        ptr->response_recv(nflds);
        const int e = ptr->get_error_code();
        // fprintf(stderr, "errcode=%d\n", e);
        if (e >= 0) {
            ptr->response_buf_remove();
        }
        // fprintf(stderr, "errcode=%d\n", ptr->get_error_code());
    } while(0);

    return INT2FIX(ptr->get_error_code());
}

VALUE ary_to_vector(VALUE ary, std::vector<dena::string_ref>& vec)
{
    VALUE ret, val;

    if (NIL_P(ary) || RARRAY_LEN(ary) == 0) {
        return ary;
    }

    ret = rb_ary_new2(RARRAY_LEN(ary));
    vec.reserve(RARRAY_LEN(ary));

    for (size_t i=0; i<RARRAY_LEN(ary); i++) {
        val = rb_ary_entry(ary, i);
        if (FIXNUM_P(val)) {
            val = rb_fix2str(val, 10);
        }
        StringValue(val);
        vec.push_back(dena::string_ref(RSTRING_PTR(val), RSTRING_LEN(val)));
        rb_ary_push(ret, val);
    }

    return ret;
}

VALUE hs_execute_single(int argc, VALUE *argv, VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    VALUE id, op, keys, limit, skip, modop, modvals;
    rb_scan_args(argc, argv, "52", &id, &op, &keys, &limit, &skip, &modop, &modvals);

    StringValue(op);
    Check_Type(keys, T_ARRAY);

    if (!NIL_P(modop)) {
        StringValue(modop);
    }

    dena::string_ref op_ref, modop_ref;
    std::vector<dena::string_ref> keyary, modary;

    op_ref = dena::string_ref(RSTRING_PTR(op), RSTRING_LEN(op));
    keys = ary_to_vector(keys, keyary);
    rb_gc_register_address(&keys);

    if (!NIL_P(modop)) {
        modop_ref = dena::string_ref(RSTRING_PTR(modop), RSTRING_LEN(modop));
        modvals = ary_to_vector(modvals, modary);
        rb_gc_register_address(&modvals);
    }

    ptr->request_buf_exec_generic(NUM2INT(id),
                                  op_ref,
                                  &keyary[0], keyary.size(),
                                  NUM2INT(limit), NUM2INT(skip),
                                  modop_ref,
                                  &modary[0], modary.size());

    if (ptr->request_send() != 0) {
        return Qnil;
    }

    rb_gc_unregister_address(&keys);

    if (!NIL_P(modop)) {
        rb_gc_unregister_address(&modvals);
    }

    size_t nflds = 0;
    ptr->response_recv(nflds);
    // fprintf(stderr, "nflds=%zu\n", nflds);

    VALUE retval = rb_ary_new();

    const int e = ptr->get_error_code();
    // fprintf(stderr, "e=%d nflds=%zu\n", e, nflds);
    rb_ary_push(retval, FIX2INT(e));

    if (e != 0) {
        const std::string s = ptr->get_error();
        rb_ary_push(retval, rb_str_new2(s.c_str()));
    } else {
        VALUE arys, ary, val;

        arys = rb_ary_new();
        const dena::string_ref *row = 0;
        while ((row = ptr->get_next_row()) != 0) {
            // fprintf(stderr, "row=%p\n", row);
            ary = rb_ary_new2(nflds);
            for (size_t i = 0; i < nflds; ++i) {
                const dena::string_ref& v = row[i];
                // fprintf(stderr, "FLD %zu v=%s vbegin=%p\n", i, std::string(v.begin(), v.size()).c_str(), v.begin());
                if (v.begin() != 0) {
                    val = rb_str_new(v.begin(), v.size());
                    rb_ary_push(ary, val);
                } else {
                    rb_ary_push(ary, Qnil);
                }
            }
            rb_ary_push(arys, ary);
        }
        rb_ary_push(retval, arys);
    }

    if (e >= 0) {
      ptr->response_buf_remove();
    }

    return retval;
}

VALUE hs_execute_multi(int argc, VALUE *argv, VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    VALUE exec_args, exec_arg;

    VALUE id, op, keys, limit, skip, modop, modvals;
    int arg = rb_scan_args(argc, argv, "16", &id, &op, &keys, &limit, &skip, &modop, &modvals);
    if (arg >= 5) {
        VALUE tmp = rb_ary_new3(id, op, keys, limit, skip, modop, modvals);
        exec_args = rb_ary_new3(tmp);
    } else if (arg == 1) {
        Check_Type(id, T_ARRAY);
        exec_args = id;
    } else {
        rb_raise(rb_eArgError, "wrong number of arguments");
    }

    for (size_t i=0; i<RARRAY_LEN(exec_args); i++) {
        exec_arg = rb_ary_entry(exec_args, i);
        Check_Type(exec_arg, T_ARRAY);

        id      = rb_ary_entry(exec_arg, 0);
        op      = rb_ary_entry(exec_arg, 1);
        keys    = rb_ary_entry(exec_arg, 2);
        limit   = rb_ary_entry(exec_arg, 3);
        skip    = rb_ary_entry(exec_arg, 4);
        modop   = rb_ary_entry(exec_arg, 5);
        modvals = rb_ary_entry(exec_arg, 6);

        StringValue(op);
        Check_Type(keys, T_ARRAY);

        if (!NIL_P(modop)) {
            StringValue(modop);
        }

        dena::string_ref op_ref, modop_ref;
        std::vector<dena::string_ref> keyary, modary;

        op_ref = dena::string_ref(RSTRING_PTR(op), RSTRING_LEN(op));
        keys = ary_to_vector(keys, keyary);
        rb_gc_register_address(&keys);

        if (!NIL_P(modop)) {
            modop_ref = dena::string_ref(RSTRING_PTR(modop), RSTRING_LEN(modop));
            modvals = ary_to_vector(modvals, modary);
            rb_gc_register_address(&modvals);
        }

        ptr->request_buf_exec_generic(NUM2INT(id),
                                      op_ref,
                                      &keyary[0], keyary.size(),
                                      NUM2INT(limit), NUM2INT(skip),
                                      modop_ref,
                                      &modary[0], modary.size());
    }

    VALUE retvals, retval;
    retvals = rb_ary_new();

    if (ptr->request_send() < 0) {
        retval = rb_ary_new();

        const int e = ptr->get_error_code();
        const std::string s = ptr->get_error();
        rb_ary_push(retval, FIX2INT(e));
        rb_ary_push(retval, rb_str_new2(s.c_str()));

        rb_ary_push(retvals, retval);
        return retvals;
    }

    for (size_t i=0; i<RARRAY_LEN(exec_args); i++) {
        retval = rb_ary_new();

        size_t nflds = 0;
        const int e = ptr->response_recv(nflds);
        rb_ary_push(retval, FIX2INT(e));
        if (e != 0) {
            const std::string s = ptr->get_error();
            rb_ary_push(retval, rb_str_new2(s.c_str()));
        } else {
            VALUE arys, ary, val;

            arys = rb_ary_new();
            const dena::string_ref *row = 0;
            while ((row = ptr->get_next_row()) != 0) {
                // fprintf(stderr, "row=%p\n", row);
                ary = rb_ary_new2(nflds);
                for (size_t i = 0; i < nflds; ++i) {
                    const dena::string_ref& v = row[i];
                    // fprintf(stderr, "FLD %zu v=%s vbegin=%p\n", i, std::string(v.begin(), v.size()).c_str(), v.begin());
                    if (v.begin() != 0) {
                        val = rb_str_new(v.begin(), v.size());
                        rb_ary_push(ary, val);
                    } else {
                        rb_ary_push(ary, Qnil);
                    }
                }
                rb_ary_push(arys, ary);
            }
            rb_ary_push(retval, arys);
        }

        if (e >= 0) {
            ptr->response_buf_remove();
        }

        rb_ary_push(retvals, retval);

        if (e < 0) {
            return retvals;
        }
    }

    return retvals;
}

VALUE hs_execute_update(VALUE self, VALUE id, VALUE op, VALUE keys, VALUE limit, VALUE skip, VALUE modvals)
{
    VALUE argv[7] = {
        id, op, keys, limit, skip, rb_str_new2("U"), modvals,
    };
    return hs_execute_single(7, argv, self);
}

VALUE hs_execute_delete(VALUE self, VALUE id, VALUE op, VALUE keys, VALUE limit, VALUE skip)
{
    VALUE argv[7] = {
        id, op, keys, limit, skip, rb_str_new2("D"), Qnil,
    };
    return hs_execute_single(7, argv, self);
}

VALUE hs_execute_insert(VALUE self, VALUE id, VALUE fvals)
{
    VALUE argv[5] = {
        id, rb_str_new2("+"), fvals, 0, 0,
    };
    return hs_execute_single(5, argv, self);
}

void parse_options(dena::config& conf, dena::socket_args& args, VALUE options)
{
    VALUE val;

    Check_Type(options, T_HASH);

    val = rb_hash_aref(options, ID2SYM(rb_intern("host")));
    if(val != Qnil)
    {
        conf["host"] = std::string(StringValuePtr(val));
        // fprintf(stderr, "host=%s\n", conf["host"].c_str());
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("port")));
    if(val != Qnil)
    {
        conf["port"] = std::string(StringValuePtr(val));
        // fprintf(stderr, "port=%s\n", conf["port"].c_str());
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("timeout")));
    if(val != Qnil)
    {
        conf["timeout"] = std::string(StringValuePtr(val));
        // fprintf(stderr, "timeout=%s\n", conf["timeout"].c_str());
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("listen_backlog")));
    if(val != Qnil)
    {
        conf["listen_backlog"] = std::string(StringValuePtr(val));
        // fprintf(stderr, "listen_backlog=%s\n", conf["listen_backlog"].c_str());
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("sndbuf")));
    if(val != Qnil)
    {
        conf["sndbuf"] = std::string(StringValuePtr(val));
        // fprintf(stderr, "sndbuf=%s\n", conf["sndbuf"].c_str());
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("rcvbuf")));
    if(val != Qnil)
    {
        conf["rcvbuf"] = std::string(StringValuePtr(val));
        // fprintf(stderr, "rcvbuf=%s\n", conf["rcvbuf"].c_str());
    }

    args.set(conf);
}

extern "C" {
    void Init_handler_socket(void)
    {
        VALUE rb_cHandlerSocket = rb_define_class("HandlerSocket", rb_cObject);

        rb_define_alloc_func(rb_cHandlerSocket, hs_alloc);
        rb_define_private_method(rb_cHandlerSocket, "initialize", (VALUE(*)(...))hs_initialize, 1);

        rb_define_method(rb_cHandlerSocket, "close", (VALUE(*)(...))hs_close, 0);
        rb_define_method(rb_cHandlerSocket, "reconnect", (VALUE(*)(...))hs_reconnect, 0);
        rb_define_method(rb_cHandlerSocket, "stable_point", (VALUE(*)(...))hs_stable_point, 0);

        rb_define_method(rb_cHandlerSocket, "error", (VALUE(*)(...))hs_error, 0);
        rb_define_method(rb_cHandlerSocket, "error_code", (VALUE(*)(...))hs_error_code, 0);

        rb_define_method(rb_cHandlerSocket, "open_index", (VALUE(*)(...))hs_open_index, 5);
        rb_define_method(rb_cHandlerSocket, "execute_single", (VALUE(*)(...))hs_execute_single, -1);
        rb_define_method(rb_cHandlerSocket, "execute_multi", (VALUE(*)(...))hs_execute_multi, -1);
        rb_define_alias(rb_cHandlerSocket, "execute_find", "execute_single");
        rb_define_method(rb_cHandlerSocket, "execute_update", (VALUE(*)(...))hs_execute_update, 6);
        rb_define_method(rb_cHandlerSocket, "execute_delete", (VALUE(*)(...))hs_execute_delete, 5);
        rb_define_method(rb_cHandlerSocket, "execute_insert", (VALUE(*)(...))hs_execute_insert, 2);
    }
}
<|endoftext|>


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

/**
 * @file camera_trigger.cpp
 *
 * External camera-IMU synchronisation and triggering via FMU auxillary pins.
 *
 * @author Mohammed Kabir <mhkabir98@gmail.com>
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <stdbool.h>
#include <nuttx/clock.h>
#include <nuttx/arch.h>
#include <systemlib/systemlib.h>
#include <systemlib/err.h>
#include <systemlib/param/param.h>
#include <uORB/uORB.h>
#include <uORB/topics/camera_trigger.h>
#include <uORB/topics/sensor_combined.h>
#include <uORB/topics/vehicle_command.h>
#include <poll.h>
#include <drivers/drv_gpio.h>
#include <drivers/drv_hrt.h>
#include <mavlink/mavlink_log.h>

extern "C" __EXPORT int camera_trigger_main(int argc, char *argv[]);

class CameraTrigger
{
public:
	/**
	 * Constructor
	 */
	CameraTrigger();

	/**
	 * Destructor, also kills task.
	 */
	~CameraTrigger();

	/**
	 * Start the task.
	 */
	void		start();

	/**
	 * Stop the task.
	 */
	void		stop();

	/**
	 * Display info.
	 */
	void		info();

	int 		pin;

private:

	struct hrt_call		_pollcall;
	struct hrt_call		_firecall;

	int 			_gpio_fd;

	int 			_polarity;
	float 			_activation_time;
	float  			_integration_time;
	float  			_transfer_time;
	uint32_t 		_trigger_seq;
	bool	 		_trigger_enabled;

	hrt_abstime		_trigger_timestamp;

	int			_sensor_sub;
	int			_vcommand_sub;

	orb_advert_t		_trigger_pub;

	struct camera_trigger_s		_trigger;
	struct sensor_combined_s	_sensor;
	struct vehicle_command_s	_command;

	param_t polarity ;
	param_t activation_time ;
	param_t integration_time ;
	param_t transfer_time ;

	/**
	 * Topic poller to check for fire info.
	 */
	static void	poll(void *arg);
	/**
	 * Fires trigger
	 */
	static void	engage(void *arg);
	/**
	 * Resets trigger
	 */
	static void	disengage(void *arg);

};

namespace camera_trigger
{

CameraTrigger	*g_camera_trigger;
}

CameraTrigger::CameraTrigger() :
	pin(1),
	_gpio_fd(-1),
	_polarity(0),
	_activation_time(0.0f),
	_integration_time(0.0f),
	_transfer_time(0.0f),
	_trigger_seq(0),
	_trigger_enabled(true),
	_trigger_timestamp(0),
	_sensor_sub(-1),
	_vcommand_sub(-1),
	_trigger_pub(-1),
	_trigger{}
{
	memset(&_trigger, 0, sizeof(_trigger));
	memset(&_command, 0, sizeof(_command));
	memset(&_sensor, 0, sizeof(_sensor));

	/* Parameters */
	polarity = param_find("TRIG_POLARITY");
	activation_time = param_find("TRIG_ACT_TIME");
	integration_time = param_find("TRIG_INT_TIME");
	transfer_time = param_find("TRIG_TRANS_TIME");
}

CameraTrigger::~CameraTrigger()
{
	camera_trigger::g_camera_trigger = nullptr;
}

void
CameraTrigger::start()
{

	_gpio_fd = open(PX4FMU_DEVICE_PATH, 0);

	if (_gpio_fd < 0) {

		warnx("GPIO device open fail");	// TODO
		stop();
	}
	else
	{
		warnx("GPIO device opened");
	}

	_sensor_sub = orb_subscribe(ORB_ID(sensor_combined));
	_vcommand_sub = orb_subscribe(ORB_ID(vehicle_command));

	param_get(polarity, &_polarity);
	param_get(activation_time, &_activation_time);
	param_get(integration_time, &_integration_time);
	param_get(transfer_time, &_transfer_time);

	ioctl(_gpio_fd, GPIO_SET_OUTPUT, pin);

	if(_polarity == 0)
	{
		ioctl(_gpio_fd, GPIO_SET, pin); 	/* GPIO pin pull high */
	}
	else if(_polarity == 1)
	{
		ioctl(_gpio_fd, GPIO_CLEAR, pin); 	/* GPIO pin pull low */
	}
	else
	{
		warnx(" invalid trigger polarity setting. stopping.");
		stop();
	}

	poll(this);

}

void
CameraTrigger::stop()
{
	hrt_cancel(&_pollcall);
	hrt_cancel(&_firecall);

	delete camera_trigger::g_camera_trigger;
}

void
CameraTrigger::poll(void *arg)
{

	CameraTrigger *trig = reinterpret_cast<CameraTrigger *>(arg);

	bool updated;
	orb_check(trig->_vcommand_sub, &updated);

	if (updated) {

		orb_copy(ORB_ID(vehicle_command), trig->_vcommand_sub, &trig->_command);

		if(trig->_command.command == VEHICLE_CMD_DO_TRIGGER_CONTROL)
		{
			if(trig->_command.param1 < 1)
			{
				if(trig->_trigger_enabled)
				{
					trig->_trigger_enabled = false ;
				}
			}
			else if(trig->_command.param1 >= 1)
			{
				if(!trig->_trigger_enabled)
				{
					trig->_trigger_enabled = true ;
				}
			}

			// Set trigger rate from command
			if(trig->_command.param2 > 0)
			{
				trig->_integration_time = trig->_command.param2;
				param_set(trig->integration_time, &(trig->_integration_time));
			}
		}
	}

	if(!trig->_trigger_enabled)	{
		hrt_call_after(&trig->_pollcall, 1000, (hrt_callout)&CameraTrigger::poll, trig);
		return;
	}

	if (hrt_elapsed_time(&trig->_trigger_timestamp) > (trig->_transfer_time + trig->_integration_time)*1000 ) {

		engage(trig);
		hrt_call_after(&trig->_firecall, trig->_activation_time*1000, (hrt_callout)&CameraTrigger::disengage, trig);

		trig->_trigger_timestamp = hrt_absolute_time();

		orb_copy(ORB_ID(sensor_combined), trig->_sensor_sub, &trig->_sensor);

		trig->_trigger.timestamp = trig->_sensor.timestamp;	/* get IMU timestamp */
		trig->_trigger.seq = trig->_trigger_seq++;

		if (trig->_trigger_pub > 0) {
			orb_publish(ORB_ID(camera_trigger), trig->_trigger_pub, &trig->_trigger);
		} else {
			trig->_trigger_pub = orb_advertise(ORB_ID(camera_trigger), &trig->_trigger);
		}

		hrt_call_after(&trig->_pollcall, (trig->_transfer_time + trig->_integration_time)*1000 , (hrt_callout)&CameraTrigger::poll, trig);
	}

}

void
CameraTrigger::engage(void *arg)
{

	CameraTrigger *trig = reinterpret_cast<CameraTrigger *>(arg);

	if(trig->_polarity == 0)  	/* ACTIVE_LOW */
	{
		ioctl(trig->_gpio_fd, GPIO_CLEAR, trig->pin);
	}
	else if(trig->_polarity == 1)	/* ACTIVE_HIGH */
	{
		ioctl(trig->_gpio_fd, GPIO_SET, trig->pin);
	}

}

void
CameraTrigger::disengage(void *arg)
{

	CameraTrigger *trig = reinterpret_cast<CameraTrigger *>(arg);

	if(trig->_polarity == 0)  	/* ACTIVE_LOW */
	{
		ioctl(trig->_gpio_fd, GPIO_SET, trig->pin);
	}
	else if(trig->_polarity == 1)	/* ACTIVE_HIGH */
	{
		ioctl(trig->_gpio_fd, GPIO_CLEAR, trig->pin);
	}

}

void
CameraTrigger::info()
{
	warnx("Trigger state : %s", _trigger_enabled ? "enabled" : "disabled");
	warnx("Trigger pin : %i", pin);
	warnx("Trigger polarity : %s", _polarity ? "ACTIVE_HIGH" : "ACTIVE_LOW");
	warnx("Shutter integration time : %.2f", (double)_integration_time);
}

static void usage()
{
	errx(1, "usage: camera_trigger {start|stop|info} [-p <n>]\n"
		     "\t-p <n>\tUse specified AUX OUT pin number (default: 1)"
		    );
}

int camera_trigger_main(int argc, char *argv[])
{
	if (argc < 2) {
		usage();
	}

	if (!strcmp(argv[1], "start")) {

		if (camera_trigger::g_camera_trigger != nullptr) {
			errx(0, "already running");
		}

		camera_trigger::g_camera_trigger = new CameraTrigger;

		if (camera_trigger::g_camera_trigger == nullptr) {
			errx(1, "alloc failed");
		}

		if (argc > 3) {

			camera_trigger::g_camera_trigger->pin = (int)argv[3];
			if (atoi(argv[3]) > 0 && atoi(argv[3]) < 6) {
				warnx("starting trigger on pin : %li ", atoi(argv[3]));
				camera_trigger::g_camera_trigger->pin = atoi(argv[3]);
			}
			else
			{
				usage();
			}
		}
		camera_trigger::g_camera_trigger->start();

		return 0;
	}

	if (camera_trigger::g_camera_trigger == nullptr) {
		errx(1, "not running");
	}

	else if (!strcmp(argv[1], "stop")) {
		camera_trigger::g_camera_trigger->stop();

	}
	else if (!strcmp(argv[1], "info")) {
		camera_trigger::g_camera_trigger->info();

	} else {
		usage();
	}

	return 0;
}

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

/**
 * @file camera_trigger.cpp
 *
 * External camera-IMU synchronisation and triggering via FMU auxillary pins.
 *
 * @author Mohammed Kabir <mhkabir98@gmail.com>
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <stdbool.h>
#include <nuttx/clock.h>
#include <nuttx/arch.h>
#include <systemlib/systemlib.h>
#include <systemlib/err.h>
#include <systemlib/param/param.h>
#include <uORB/uORB.h>
#include <uORB/topics/camera_trigger.h>
#include <uORB/topics/sensor_combined.h>
#include <uORB/topics/vehicle_command.h>
#include <poll.h>
#include <drivers/drv_gpio.h>
#include <drivers/drv_hrt.h>
#include <mavlink/mavlink_log.h>

extern "C" __EXPORT int camera_trigger_main(int argc, char *argv[]);

class CameraTrigger
{
public:
	/**
	 * Constructor
	 */
	CameraTrigger();

	/**
	 * Destructor, also kills task.
	 */
	~CameraTrigger();

	/**
	 * Start the task.
	 */
	void		start();

	/**
	 * Stop the task.
	 */
	void		stop();

	/**
	 * Display info.
	 */
	void		info();

	int 		pin;

private:

	struct hrt_call		_pollcall;
	struct hrt_call		_firecall;

	int 			_gpio_fd;

	int 			_polarity;
	float 			_activation_time;
	float  			_integration_time;
	float  			_transfer_time;
	uint32_t 		_trigger_seq;
	bool	 		_trigger_enabled;

	hrt_abstime		_trigger_timestamp;

	int			_sensor_sub;
	int			_vcommand_sub;

	orb_advert_t		_trigger_pub;

	struct camera_trigger_s		_trigger;
	struct sensor_combined_s	_sensor;
	struct vehicle_command_s	_command;

	param_t polarity ;
	param_t activation_time ;
	param_t integration_time ;
	param_t transfer_time ;

	/**
	 * Topic poller to check for fire info.
	 */
	static void	poll(void *arg);
	/**
	 * Fires trigger
	 */
	static void	engage(void *arg);
	/**
	 * Resets trigger
	 */
	static void	disengage(void *arg);

};

namespace camera_trigger
{

CameraTrigger	*g_camera_trigger;
}

CameraTrigger::CameraTrigger() :
	pin(1),
	_gpio_fd(-1),
	_polarity(0),
	_activation_time(0.0f),
	_integration_time(0.0f),
	_transfer_time(0.0f),
	_trigger_seq(0),
	_trigger_enabled(true),
	_trigger_timestamp(0),
	_sensor_sub(-1),
	_vcommand_sub(-1),
	_trigger_pub(-1),
	_trigger{}
{
	memset(&_trigger, 0, sizeof(_trigger));
	memset(&_command, 0, sizeof(_command));
	memset(&_sensor, 0, sizeof(_sensor));

	memset(&_pollcall, 0, sizeof(_pollcall));
	memset(&_firecall, 0, sizeof(_firecall));

	/* Parameters */
	polarity = param_find("TRIG_POLARITY");
	activation_time = param_find("TRIG_ACT_TIME");
	integration_time = param_find("TRIG_INT_TIME");
	transfer_time = param_find("TRIG_TRANS_TIME");
}

CameraTrigger::~CameraTrigger()
{
	camera_trigger::g_camera_trigger = nullptr;
}

void
CameraTrigger::start()
{

	_gpio_fd = open(PX4FMU_DEVICE_PATH, 0);

	if (_gpio_fd < 0) {

		warnx("GPIO device open fail");	// TODO
		stop();
	}
	else
	{
		warnx("GPIO device opened");
	}

	_sensor_sub = orb_subscribe(ORB_ID(sensor_combined));
	_vcommand_sub = orb_subscribe(ORB_ID(vehicle_command));

	param_get(polarity, &_polarity);
	param_get(activation_time, &_activation_time);
	param_get(integration_time, &_integration_time);
	param_get(transfer_time, &_transfer_time);

	ioctl(_gpio_fd, GPIO_SET_OUTPUT, pin);

	if(_polarity == 0)
	{
		ioctl(_gpio_fd, GPIO_SET, pin); 	/* GPIO pin pull high */
	}
	else if(_polarity == 1)
	{
		ioctl(_gpio_fd, GPIO_CLEAR, pin); 	/* GPIO pin pull low */
	}
	else
	{
		warnx(" invalid trigger polarity setting. stopping.");
		stop();
	}

	hrt_call_every(&_pollcall, 0, 1000, (hrt_callout)&CameraTrigger::poll, this);

}

void
CameraTrigger::stop()
{
	hrt_cancel(&_firecall);
	hrt_cancel(&_pollcall);

	delete camera_trigger::g_camera_trigger;
}

void
CameraTrigger::poll(void *arg)
{

	CameraTrigger *trig = reinterpret_cast<CameraTrigger *>(arg);

	bool updated;
	orb_check(trig->_vcommand_sub, &updated);

	if (updated) {

		orb_copy(ORB_ID(vehicle_command), trig->_vcommand_sub, &trig->_command);

		if(trig->_command.command == VEHICLE_CMD_DO_TRIGGER_CONTROL)
		{
			if(trig->_command.param1 < 1)
			{
				if(trig->_trigger_enabled)
				{
					trig->_trigger_enabled = false ;
				}
			}
			else if(trig->_command.param1 >= 1)
			{
				if(!trig->_trigger_enabled)
				{
					trig->_trigger_enabled = true ;
				}
			}

			// Set trigger rate from command
			if(trig->_command.param2 > 0)
			{
				trig->_integration_time = trig->_command.param2;
				param_set(trig->integration_time, &(trig->_integration_time));
			}
		}
	}

	if(!trig->_trigger_enabled)	{
		return;
	}

	if (hrt_elapsed_time(&trig->_trigger_timestamp) >= (trig->_transfer_time + trig->_integration_time)*1000 ) {

		engage(trig);
		trig->_trigger_timestamp = hrt_absolute_time();
		hrt_call_after(&trig->_firecall, trig->_activation_time*1000, (hrt_callout)&CameraTrigger::disengage, trig);

		orb_copy(ORB_ID(sensor_combined), trig->_sensor_sub, &trig->_sensor);

		trig->_trigger.timestamp = trig->_sensor.timestamp;	/* get IMU timestamp */
		trig->_trigger.seq = trig->_trigger_seq++;

		if (trig->_trigger_pub > 0) {
			orb_publish(ORB_ID(camera_trigger), trig->_trigger_pub, &trig->_trigger);
		} else {
			trig->_trigger_pub = orb_advertise(ORB_ID(camera_trigger), &trig->_trigger);
		}

	}

}

void
CameraTrigger::engage(void *arg)
{

	CameraTrigger *trig = reinterpret_cast<CameraTrigger *>(arg);

	if(trig->_polarity == 0)  	/* ACTIVE_LOW */
	{
		ioctl(trig->_gpio_fd, GPIO_CLEAR, trig->pin);
	}
	else if(trig->_polarity == 1)	/* ACTIVE_HIGH */
	{
		ioctl(trig->_gpio_fd, GPIO_SET, trig->pin);
	}

}

void
CameraTrigger::disengage(void *arg)
{

	CameraTrigger *trig = reinterpret_cast<CameraTrigger *>(arg);

	if(trig->_polarity == 0)  	/* ACTIVE_LOW */
	{
		ioctl(trig->_gpio_fd, GPIO_SET, trig->pin);
	}
	else if(trig->_polarity == 1)	/* ACTIVE_HIGH */
	{
		ioctl(trig->_gpio_fd, GPIO_CLEAR, trig->pin);
	}

}

void
CameraTrigger::info()
{
	warnx("Trigger state : %s", _trigger_enabled ? "enabled" : "disabled");
	warnx("Trigger pin : %i", pin);
	warnx("Trigger polarity : %s", _polarity ? "ACTIVE_HIGH" : "ACTIVE_LOW");
	warnx("Shutter integration time : %.2f", (double)_integration_time);
}

static void usage()
{
	errx(1, "usage: camera_trigger {start|stop|info} [-p <n>]\n"
		     "\t-p <n>\tUse specified AUX OUT pin number (default: 1)"
		    );
}

int camera_trigger_main(int argc, char *argv[])
{
	if (argc < 2) {
		usage();
	}

	if (!strcmp(argv[1], "start")) {

		if (camera_trigger::g_camera_trigger != nullptr) {
			errx(0, "already running");
		}

		camera_trigger::g_camera_trigger = new CameraTrigger;

		if (camera_trigger::g_camera_trigger == nullptr) {
			errx(1, "alloc failed");
		}

		if (argc > 3) {

			camera_trigger::g_camera_trigger->pin = (int)argv[3];
			if (atoi(argv[3]) > 0 && atoi(argv[3]) < 6) {
				warnx("starting trigger on pin : %li ", atoi(argv[3]));
				camera_trigger::g_camera_trigger->pin = atoi(argv[3]);
			}
			else
			{
				usage();
			}
		}
		camera_trigger::g_camera_trigger->start();

		return 0;
	}

	if (camera_trigger::g_camera_trigger == nullptr) {
		errx(1, "not running");
	}

	else if (!strcmp(argv[1], "stop")) {
		camera_trigger::g_camera_trigger->stop();

	}
	else if (!strcmp(argv[1], "info")) {
		camera_trigger::g_camera_trigger->info();

	} else {
		usage();
	}

	return 0;
}

<|endoftext|>