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

  Library   : Image Registration Toolkit (IRTK)
  Module    : $Id$
  Copyright : Imperial College, Department of Computing
              Visual Information Processing (VIP), 2008 onwards
  Date      : $Date$
  Version   : $Revision$
  Changes   : $Author$

=========================================================================*/

#include <irtkImage.h>

#include <irtkTransformation.h>

char *target_name = NULL;
char *dofin_name  = NULL;
char *dofout_name = NULL;

irtkGreyImage *target;
irtkMultiLevelFreeFormTransformation *mffd;

#ifdef WIN32
#include <time.h>
#include <windows.h>

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
#endif

struct timezone
{
    int  tz_minuteswest; /* minutes W of Greenwich */
    int  tz_dsttime;     /* type of dst correction */
};

int gettimeofday(struct timeval *tv, struct timezone *tz)
{
    FILETIME ft;
    unsigned __int64 tmpres = 0;
    static int tzflag;

    if (NULL != tv)
    {
        GetSystemTimeAsFileTime(&ft);

        tmpres |= ft.dwHighDateTime;
        tmpres <<= 32;
        tmpres |= ft.dwLowDateTime;

        /*converting file time to unix epoch*/
        tmpres -= DELTA_EPOCH_IN_MICROSECS;
        tmpres /= 10;  /*convert into microseconds*/
        tv->tv_sec = (long)(tmpres / 1000000UL);
        tv->tv_usec = (long)(tmpres % 1000000UL);
    }

    if (NULL != tz)
    {
        if (!tzflag)
        {
            _tzset();
            tzflag++;
        }
        tz->tz_minuteswest = _timezone / 60;
        tz->tz_dsttime = _daylight;
    }

    return 0;
}
#else
#include <sys/time.h>
#endif

#include <nr.h>
#include <nrutil.h>

void usage()
{
  cerr << "Usage: ffdadd [target] [dofin] [dofout] [options]" << endl;
  cerr << "where the following options are supported:\n" << endl;
  cerr << "<-Tx1 value>  Region of interest in target image" << endl;
  cerr << "<-Ty1 value>  Region of interest in target image" << endl;
  cerr << "<-Tz1 value>  Region of interest in target image" << endl;
  cerr << "<-Tt1 value>  Region of interest in target image" << endl;
  cerr << "<-Tx2 value>  Region of interest in target image" << endl;
  cerr << "<-Ty2 value>  Region of interest in target image" << endl;
  cerr << "<-Tz2 value>  Region of interest in target image" << endl;
  cerr << "<-Tt2 value>  Region of interest in target image" << endl;
  cerr << "<-dx  value>  Control point spacing for x" << endl;
  cerr << "<-dy  value>  Control point spacing for y" << endl;
  cerr << "<-dz  value>  Control point spacing for z" << endl;
  cerr << "<-dt  value>  Control point spacing for t" << endl;
  cerr << "<-ds  value>  Control point spacing for x, y, z and t" << endl;
  cerr << "<-3D>         Generate 3D FFD (default)" << endl;
  cerr << "<-4D>         Generate 4D FFD" << endl;
  cout << endl;
  exit(1);
}

int main(int argc, char **argv)
{
  double dx, dy, dz, dt, noise;
  int i1, j1, k1, l1, i2, j2, k2, l2, ok, fluid, ffd4D;

  // Check command line
  if (argc < 4) {
    usage();
  }

  // Parse file names
  target_name = argv[1];
  argc--;
  argv++;
  dofin_name  = argv[1];
  argc--;
  argv++;
  dofout_name = argv[1];
  argc--;
  argv++;

  // Read image image
  cout << "Reading image ... "; cout.flush();
  target = new irtkGreyImage;
  target->Read(target_name);
  cout << "done" << endl;

  // Fix ROI
  i1 = 0;
  j1 = 0;
  k1 = 0;
  l1 = 0;
  i2 = target->GetX();
  j2 = target->GetY();
  k2 = target->GetZ();
  l2 = target->GetT();

  // Fix spacing
  dx = 20;
  dy = 20;
  dz = 20;
  dt = 20;

  // No 4D FFD
  ffd4D = false;

  // No fluid
  fluid = false;

  // Don't add noise
  noise = 0;

  // Parse remaining parameters
  while (argc > 1) {
    ok = false;
    if ((ok == false) && (strcmp(argv[1], "-Tx1") == 0)) {
      argc--;
      argv++;
      i1 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Tx2") == 0)) {
      argc--;
      argv++;
      i2 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Ty1") == 0)) {
      argc--;
      argv++;
      j1 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Ty2") == 0)) {
      argc--;
      argv++;
      j2 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Tz1") == 0)) {
      argc--;
      argv++;
      k1 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Tz2") == 0)) {
      argc--;
      argv++;
      k2 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Tt1") == 0)) {
      argc--;
      argv++;
      l1 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Tt2") == 0)) {
      argc--;
      argv++;
      l2 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-dx") == 0)) {
      argc--;
      argv++;
      dx = atof(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-dy") == 0)) {
      argc--;
      argv++;
      dy = atof(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-dz") == 0)) {
      argc--;
      argv++;
      dz = atof(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-dt") == 0)) {
      argc--;
      argv++;
      dt = atof(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-ds") == 0)) {
      argc--;
      argv++;
      dx = atof(argv[1]);
      dy = atof(argv[1]);
      dz = atof(argv[1]);
      dt = atof(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-fluid") == 0)) {
      argc--;
      argv++;
      fluid = true;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-3D") == 0)) {
      argc--;
      argv++;
      ffd4D = false;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-4D") == 0)) {
      argc--;
      argv++;
      ffd4D = true;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-noise") == 0)) {
      argc--;
      argv++;
      noise = atof(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if (ok == false) {
      cerr << "Can not parse argument " << argv[1] << endl;
      usage();
    }
  }

  // Read transformation
  if (fluid == true) {
    mffd = new irtkFluidFreeFormTransformation;
  } else {
    mffd = new irtkMultiLevelFreeFormTransformation;
  }
  mffd->irtkTransformation::Read(dofin_name);

  // If there is an region of interest, use it
  if ((i1 != 0) || (i2 != target->GetX()) ||
      (j1 != 0) || (j2 != target->GetY()) ||
      (k1 != 0) || (k2 != target->GetZ()) ||
      (l1 != 0) || (l2 != target->GetT())) {
    *target = target->GetRegion(i1, j1, k1, l1, i2, j2, k2, l2);
  }

  if (ffd4D == false) {
    // Create free-form transformation
    irtkBSplineFreeFormTransformation3D *affd = new irtkBSplineFreeFormTransformation(*target, dx, dy, dz);

    // Add noise to the transformation
    if (noise > 0) {
      int i;
      long temp;

      timeval tv;
      gettimeofday(&tv, NULL);
      temp = -tv.tv_usec;

      for (i = 0; i < affd->NumberOfDOFs(); i++) affd->Put(i, noise*gasdev(&temp));
    }

    // Add and write file
    mffd->PushLocalTransformation(affd);
  } else {
    // Create free-form transformation
    irtkBSplineFreeFormTransformation4D *affd = new irtkBSplineFreeFormTransformation4D(*target, dx, dy, dz, dt);

    // Add noise to the transformation
    if (noise > 0) {
      int i;
      long temp;

      timeval tv;
      gettimeofday(&tv, NULL);
      temp = -tv.tv_usec;

      for (i = 0; i < affd->NumberOfDOFs(); i++) affd->Put(i, noise*gasdev(&temp));
    }

    // Add and write file
    mffd->PushLocalTransformation(affd);
  }

  mffd->irtkTransformation::Write(dofout_name);
}
<commit_msg>Removed recipes gasdev function from ffdadd.cc<commit_after>/*=========================================================================

  Library   : Image Registration Toolkit (IRTK)
  Module    : $Id$
  Copyright : Imperial College, Department of Computing
              Visual Information Processing (VIP), 2008 onwards
  Date      : $Date$
  Version   : $Revision$
  Changes   : $Author$

=========================================================================*/

#include <irtkImage.h>

#include <irtkTransformation.h>

char *target_name = NULL;
char *dofin_name  = NULL;
char *dofout_name = NULL;

irtkGreyImage *target;
irtkMultiLevelFreeFormTransformation *mffd;

#ifdef WIN32
#include <time.h>
#include <windows.h>

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
#endif

struct timezone
{
    int  tz_minuteswest; /* minutes W of Greenwich */
    int  tz_dsttime;     /* type of dst correction */
};

int gettimeofday(struct timeval *tv, struct timezone *tz)
{
    FILETIME ft;
    unsigned __int64 tmpres = 0;
    static int tzflag;

    if (NULL != tv)
    {
        GetSystemTimeAsFileTime(&ft);

        tmpres |= ft.dwHighDateTime;
        tmpres <<= 32;
        tmpres |= ft.dwLowDateTime;

        /*converting file time to unix epoch*/
        tmpres -= DELTA_EPOCH_IN_MICROSECS;
        tmpres /= 10;  /*convert into microseconds*/
        tv->tv_sec = (long)(tmpres / 1000000UL);
        tv->tv_usec = (long)(tmpres % 1000000UL);
    }

    if (NULL != tz)
    {
        if (!tzflag)
        {
            _tzset();
            tzflag++;
        }
        tz->tz_minuteswest = _timezone / 60;
        tz->tz_dsttime = _daylight;
    }

    return 0;
}
#else
#include <sys/time.h>
#endif

#include <boost/random.hpp>
#include <boost/random/normal_distribution.hpp>

void usage()
{
  cerr << "Usage: ffdadd [target] [dofin] [dofout] [options]" << endl;
  cerr << "where the following options are supported:\n" << endl;
  cerr << "<-Tx1 value>  Region of interest in target image" << endl;
  cerr << "<-Ty1 value>  Region of interest in target image" << endl;
  cerr << "<-Tz1 value>  Region of interest in target image" << endl;
  cerr << "<-Tt1 value>  Region of interest in target image" << endl;
  cerr << "<-Tx2 value>  Region of interest in target image" << endl;
  cerr << "<-Ty2 value>  Region of interest in target image" << endl;
  cerr << "<-Tz2 value>  Region of interest in target image" << endl;
  cerr << "<-Tt2 value>  Region of interest in target image" << endl;
  cerr << "<-dx  value>  Control point spacing for x" << endl;
  cerr << "<-dy  value>  Control point spacing for y" << endl;
  cerr << "<-dz  value>  Control point spacing for z" << endl;
  cerr << "<-dt  value>  Control point spacing for t" << endl;
  cerr << "<-ds  value>  Control point spacing for x, y, z and t" << endl;
  cerr << "<-3D>         Generate 3D FFD (default)" << endl;
  cerr << "<-4D>         Generate 4D FFD" << endl;
  cout << endl;
  exit(1);
}

int main(int argc, char **argv)
{
  double dx, dy, dz, dt, noise;
  int i1, j1, k1, l1, i2, j2, k2, l2, ok, fluid, ffd4D;

  // Check command line
  if (argc < 4) {
    usage();
  }

  // Parse file names
  target_name = argv[1];
  argc--;
  argv++;
  dofin_name  = argv[1];
  argc--;
  argv++;
  dofout_name = argv[1];
  argc--;
  argv++;

  // Read image image
  cout << "Reading image ... "; cout.flush();
  target = new irtkGreyImage;
  target->Read(target_name);
  cout << "done" << endl;

  // Fix ROI
  i1 = 0;
  j1 = 0;
  k1 = 0;
  l1 = 0;
  i2 = target->GetX();
  j2 = target->GetY();
  k2 = target->GetZ();
  l2 = target->GetT();

  // Fix spacing
  dx = 20;
  dy = 20;
  dz = 20;
  dt = 20;

  // No 4D FFD
  ffd4D = false;

  // No fluid
  fluid = false;

  // Don't add noise
  noise = 0;

  // Parse remaining parameters
  while (argc > 1) {
    ok = false;
    if ((ok == false) && (strcmp(argv[1], "-Tx1") == 0)) {
      argc--;
      argv++;
      i1 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Tx2") == 0)) {
      argc--;
      argv++;
      i2 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Ty1") == 0)) {
      argc--;
      argv++;
      j1 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Ty2") == 0)) {
      argc--;
      argv++;
      j2 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Tz1") == 0)) {
      argc--;
      argv++;
      k1 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Tz2") == 0)) {
      argc--;
      argv++;
      k2 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Tt1") == 0)) {
      argc--;
      argv++;
      l1 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-Tt2") == 0)) {
      argc--;
      argv++;
      l2 = atoi(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-dx") == 0)) {
      argc--;
      argv++;
      dx = atof(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-dy") == 0)) {
      argc--;
      argv++;
      dy = atof(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-dz") == 0)) {
      argc--;
      argv++;
      dz = atof(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-dt") == 0)) {
      argc--;
      argv++;
      dt = atof(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-ds") == 0)) {
      argc--;
      argv++;
      dx = atof(argv[1]);
      dy = atof(argv[1]);
      dz = atof(argv[1]);
      dt = atof(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-fluid") == 0)) {
      argc--;
      argv++;
      fluid = true;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-3D") == 0)) {
      argc--;
      argv++;
      ffd4D = false;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-4D") == 0)) {
      argc--;
      argv++;
      ffd4D = true;
      ok = true;
    }
    if ((ok == false) && (strcmp(argv[1], "-noise") == 0)) {
      argc--;
      argv++;
      noise = atof(argv[1]);
      argc--;
      argv++;
      ok = true;
    }
    if (ok == false) {
      cerr << "Can not parse argument " << argv[1] << endl;
      usage();
    }
  }

  // Read transformation
  if (fluid == true) {
    mffd = new irtkFluidFreeFormTransformation;
  } else {
    mffd = new irtkMultiLevelFreeFormTransformation;
  }
  mffd->irtkTransformation::Read(dofin_name);

  // If there is an region of interest, use it
  if ((i1 != 0) || (i2 != target->GetX()) ||
      (j1 != 0) || (j2 != target->GetY()) ||
      (k1 != 0) || (k2 != target->GetZ()) ||
      (l1 != 0) || (l2 != target->GetT())) {
    *target = target->GetRegion(i1, j1, k1, l1, i2, j2, k2, l2);
  }

  if (ffd4D == false) {
    // Create free-form transformation
    irtkBSplineFreeFormTransformation3D *affd = new irtkBSplineFreeFormTransformation(*target, dx, dy, dz);

    // Add noise to the transformation
    if (noise > 0) {
      int i;
      long temp;

      timeval tv;
      gettimeofday(&tv, NULL);
      temp = -tv.tv_usec;

      boost::mt19937 rng;
      rng.seed(temp);

      boost::normal_distribution<> nd(0.0, 1.0);
      boost::variate_generator<boost::mt19937&,
 			       boost::normal_distribution<> > var_nor(rng, nd);

      for (i = 0; i < affd->NumberOfDOFs(); i++) affd->Put(i, noise*var_nor());
    }

    // Add and write file
    mffd->PushLocalTransformation(affd);
  } else {
    // Create free-form transformation
    irtkBSplineFreeFormTransformation4D *affd = new irtkBSplineFreeFormTransformation4D(*target, dx, dy, dz, dt);

    // Add noise to the transformation
    if (noise > 0) {
      int i;
      long temp;

      timeval tv;
      gettimeofday(&tv, NULL);
      temp = -tv.tv_usec;

      boost::mt19937 rng;
      rng.seed(temp);

      boost::normal_distribution<> nd(0.0, 1.0);
      boost::variate_generator<boost::mt19937&,
                               boost::normal_distribution<> > var_nor(rng, nd);

      for (i = 0; i < affd->NumberOfDOFs(); i++) affd->Put(i, noise*var_nor());
    }

    // Add and write file
    mffd->PushLocalTransformation(affd);
  }

  mffd->irtkTransformation::Write(dofout_name);
}
<|endoftext|>


<commit_before>// Copyright (C) 2010-2014 Joshua Boyce.
// See the file COPYING for copying permission.

#include <thread>

#include <windows.h>

#include <hadesmem/config.hpp>
#include <hadesmem/detail/self_path.hpp>
#include <hadesmem/detail/trace.hpp>
#include <hadesmem/error.hpp>

#include "../cerberus/plugin.hpp"

#include "radar.hpp"
#include "root_window.hpp"

namespace
{
std::size_t g_on_frame_callback_id{};

std::unique_ptr<std::thread> g_window_thread{};
}

extern "C" HADESMEM_DETAIL_DLLEXPORT DWORD_PTR
  LoadPlugin(hadesmem::cerberus::PluginInterface* cerberus)
  HADESMEM_DETAIL_NOEXCEPT
{
  try
  {
    HADESMEM_DETAIL_TRACE_A("Initializing.");

    // Using a wrapper lambda to work around a GCC link error on x86
    auto const window_thread = []()
    {
      WindowThread(
        hadesmem::detail::GetHandleToSelf(), nullptr, nullptr, SW_SHOW);
    };
    g_window_thread.reset(new std::thread(window_thread));
    g_window_thread->detach();

    InitializeRadar(cerberus);

    return 0;
  }
  catch (...)
  {
    HADESMEM_DETAIL_TRACE_A(
      boost::current_exception_diagnostic_information().c_str());
    HADESMEM_DETAIL_ASSERT(false);

    return 1;
  }
}

extern "C" HADESMEM_DETAIL_DLLEXPORT DWORD_PTR
  UnloadPlugin(hadesmem::cerberus::PluginInterface* cerberus)
  HADESMEM_DETAIL_NOEXCEPT
{
  try
  {
    HADESMEM_DETAIL_TRACE_A("Cleaning up.");

    CleanupRadar(cerberus);

    auto const hwnd = GetWindowHandle();
    if (hwnd && ::SendMessageW(hwnd, WM_CLOSE, 0, 0))
    {
      DWORD const last_error = ::GetLastError();
      HADESMEM_DETAIL_THROW_EXCEPTION(
        hadesmem::Error{} << hadesmem::ErrorString{"SendMessageW failed."}
                          << hadesmem::ErrorCodeWinLast{last_error});
    }

    auto const& thread = GetThreadHandle();
    if (thread.IsValid())
    {
      DWORD const wait_result =
        ::WaitForSingleObject(thread.GetHandle(), INFINITE);
      if (wait_result != WAIT_OBJECT_0)
      {
        DWORD const last_error = ::GetLastError();
        HADESMEM_DETAIL_THROW_EXCEPTION(
          hadesmem::Error{}
          << hadesmem::ErrorString{"WaitForSingleObject failed."}
          << hadesmem::ErrorCodeWinLast{last_error}
          << hadesmem::ErrorCodeWinOther(wait_result));
      }
    }

    return 0;
  }
  catch (...)
  {
    HADESMEM_DETAIL_TRACE_A(
      boost::current_exception_diagnostic_information().c_str());
    HADESMEM_DETAIL_ASSERT(false);

    return 1;
  }
}

BOOL WINAPI
  DllMain(HINSTANCE /*instance*/, DWORD /*reason*/, LPVOID /*reserved*/)
  HADESMEM_DETAIL_NOEXCEPT
{
  return TRUE;
}
<commit_msg>* [Cerberus] Remove dead variable. * [Cerberus] Fix bug.<commit_after>// Copyright (C) 2010-2014 Joshua Boyce.
// See the file COPYING for copying permission.

#include <thread>

#include <windows.h>

#include <hadesmem/config.hpp>
#include <hadesmem/detail/self_path.hpp>
#include <hadesmem/detail/trace.hpp>
#include <hadesmem/error.hpp>

#include "../cerberus/plugin.hpp"

#include "radar.hpp"
#include "root_window.hpp"

namespace
{
std::unique_ptr<std::thread> g_window_thread{};
}

extern "C" HADESMEM_DETAIL_DLLEXPORT DWORD_PTR
  LoadPlugin(hadesmem::cerberus::PluginInterface* cerberus)
  HADESMEM_DETAIL_NOEXCEPT
{
  try
  {
    HADESMEM_DETAIL_TRACE_A("Initializing.");

    // Preemptively fix a potential order of destruction issue by ensuring this
    // is used very early.
    auto const& thread = GetThreadHandle();
    (void)thread;

    // Using a wrapper lambda to work around a GCC link error on x86
    auto const window_thread = []()
    {
      WindowThread(
        hadesmem::detail::GetHandleToSelf(), nullptr, nullptr, SW_SHOW);
    };
    g_window_thread.reset(new std::thread(window_thread));
    g_window_thread->detach();

    InitializeRadar(cerberus);

    return 0;
  }
  catch (...)
  {
    HADESMEM_DETAIL_TRACE_A(
      boost::current_exception_diagnostic_information().c_str());
    HADESMEM_DETAIL_ASSERT(false);

    return 1;
  }
}

extern "C" HADESMEM_DETAIL_DLLEXPORT DWORD_PTR
  UnloadPlugin(hadesmem::cerberus::PluginInterface* cerberus)
  HADESMEM_DETAIL_NOEXCEPT
{
  try
  {
    HADESMEM_DETAIL_TRACE_A("Cleaning up.");

    CleanupRadar(cerberus);

    auto const hwnd = GetWindowHandle();
    if (hwnd && ::SendMessageW(hwnd, WM_CLOSE, 0, 0))
    {
      DWORD const last_error = ::GetLastError();
      HADESMEM_DETAIL_THROW_EXCEPTION(
        hadesmem::Error{} << hadesmem::ErrorString{"SendMessageW failed."}
                          << hadesmem::ErrorCodeWinLast{last_error});
    }

    auto const& thread = GetThreadHandle();
    if (thread.IsValid())
    {
      DWORD const wait_result =
        ::WaitForSingleObject(thread.GetHandle(), INFINITE);
      if (wait_result != WAIT_OBJECT_0)
      {
        DWORD const last_error = ::GetLastError();
        HADESMEM_DETAIL_THROW_EXCEPTION(
          hadesmem::Error{}
          << hadesmem::ErrorString{"WaitForSingleObject failed."}
          << hadesmem::ErrorCodeWinLast{last_error}
          << hadesmem::ErrorCodeWinOther(wait_result));
      }
    }

    return 0;
  }
  catch (...)
  {
    HADESMEM_DETAIL_TRACE_A(
      boost::current_exception_diagnostic_information().c_str());
    HADESMEM_DETAIL_ASSERT(false);

    return 1;
  }
}

BOOL WINAPI
  DllMain(HINSTANCE /*instance*/, DWORD /*reason*/, LPVOID /*reserved*/)
  HADESMEM_DETAIL_NOEXCEPT
{
  return TRUE;
}
<|endoftext|>


<commit_before>//===========================================
//  PC-BSD source code
//  Copyright (c) 2016, PC-BSD Software/iXsystems
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================
#include "sysadm-client.h"
#include <QSslConfiguration>
#include <QJsonArray>

// === PUBLIC ===
sysadm_client::sysadm_client(){
  SOCKET = new QWebSocket("sysadm-client", QWebSocketProtocol::VersionLatest, this);
    SOCKET->setSslConfiguration(QSslConfiguration::defaultConfiguration());
    QList<QSslError> ignored; ignored << QSslError(QSslError::SelfSignedCertificate) << QSslError(QSslError::HostNameMismatch);
    SOCKET->ignoreSslErrors(ignored);
    //SOCKET->ignoreSslErrors();
    //use the new Qt5 connection syntax for compile time checks that connections are valid
    connect(SOCKET, &QWebSocket::connected, this, &sysadm_client::socketConnected);
    connect(SOCKET, &QWebSocket::disconnected, this, &sysadm_client::socketClosed);
    connect(SOCKET, &QWebSocket::textMessageReceived, this, &sysadm_client::socketMessage);
    //Old connect syntax for the "error" signal (special note about issues in the docs)
    connect(SOCKET, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)) );
    connect(SOCKET, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(socketSslErrors(const QList<QSslError>&)) );
  keepActive=false; //not setup yet
  settings = new QSettings("PC-BSD","sysadm-client", this);
}

sysadm_client::~sysadm_client(){

}

// Overall Connection functions (start/stop)
void sysadm_client::openConnection(QString user, QString pass, QString hostIP){
  cuser = user; cpass = pass; chost = hostIP;
  qDebug() << "Client: Setup connection:" << user << pass << hostIP;
  setupSocket();
}

void sysadm_client::openConnection(QString authkey, QString hostIP){
  cauthkey = authkey; chost = hostIP;
  setupSocket();
}

void sysadm_client::closeConnection(){
  keepActive = false;
  //de-authorize the current auth token
  cauthkey.clear();
  performAuth();
  //Now close the connection
  SOCKET->close(QWebSocketProtocol::CloseCodeNormal, "sysadm-client closed");
}

// Connection Hosts Database Access
QStringList sysadm_client::knownHosts(){
  //Returns: <IP>::::<Name>
  QStringList hosts =settings->value("knownhosts",QStringList()).toStringList();
  for(int i=0; i<hosts.length(); i++){
    hosts[i].append("::::" + settings->value("hostnames/"+hosts[i],"").toString() );
  }
  return hosts;
}

void sysadm_client::saveHost(QString IP, QString name){
  QStringList hosts = settings->value("knownhosts",QStringList()).toStringList();
  hosts << IP;
  hosts.removeDuplicates();
  settings->setValue("knownhosts",hosts);
  settings->setValue("hostnames/"+IP,name);
}

void sysadm_client::removeHost(QString IP){
  QStringList hosts = settings->value("knownhosts",QStringList()).toStringList();
  hosts.removeAll(IP);
  settings->setValue("knownhosts",hosts);
  settings->remove("hostnames/"+IP);
}

// Register for Event Notifications (no notifications by default)
void sysadm_client::registerForEvents(EVENT_TYPE event, bool receive){
  bool set = events.contains(event);
  if( set && receive){ return; } //already registered
  else if(!set && !receive){ return; } //already unregistered
  else if(set){ events << event; }
  else{ events.removeAll(event); }
  //Since this can be setup before the socket is connected - see if we can send this message right away
  if(SOCKET->isValid()){
    sendEventSubscription(event, receive);
  }

}

// Messages which are still pending a response
QStringList sysadm_client::pending(){ return PENDING; } //returns only the "id" for each

// Fetch a message from the recent cache
QJsonObject sysadm_client::cachedRequest(QString id){
  if(SENT.contains(id)){ return SENT.value(id); }
  else{ return QJsonObject(); }
}

QJsonValue sysadm_client::cachedReply(QString id){
  if(BACK.contains(id)){ return BACK.value(id); }
  else{ return QJsonObject(); }
}

// === PRIVATE ===
//Functions to do the initial socket setup
void sysadm_client::setupSocket(){
  qDebug() << "Setup Socket:" << SOCKET->isValid();
  if(SOCKET->isValid()){ return; }
  //uses chost for setup
  // - assemble the host URL
  if(chost.contains("://")){ chost = chost.section("://",1,1); } //Chop off the custom http/ftp/other header (always need "wss://")
  QString url = "wss://"+chost;
  bool hasport = false;
  url.section(":",-1).toInt(&hasport); //check if the last piece of the url is a valid number
  //Could add a check for a valid port number as well - but that is a bit overkill right now
  if(!hasport){ url.append(":"+QString::number(WSPORTDEFAULT)); }
  qDebug() << " - URL:" << url;
  SOCKET->open(QUrl(url));
}

void sysadm_client::performAuth(QString user, QString pass){
  //uses cauthkey if empty inputs
  QJsonObject obj;
  obj.insert("namespace","rpc");
  obj.insert("id","sysadm-client-auth-auto");
  bool noauth = false;
  if(user.isEmpty() && pass.isEmpty()){
    if(cauthkey.isEmpty()){
      //Nothing to authenticate - de-auth the connection instead
      obj.insert("name","auth_clear");
      obj.insert("args","");
      noauth = true;
    }else{
      //Saved token authentication
      obj.insert("name","auth_token");
      QJsonObject arg;
	arg.insert("token",cauthkey);
      obj.insert("args", arg);
    }
  }else{
    //User/password authentication
    obj.insert("name","auth");
    QJsonObject arg;
      arg.insert("username",user);
      arg.insert("password",pass);
    obj.insert("args", arg);
  }
  sendSocketMessage(obj);
  if(noauth){ emit clientUnauthorized(); }
}

//Communication subroutines with the server (block until message comes back)
void sysadm_client::sendEventSubscription(EVENT_TYPE event, bool subscribe){
  QJsonObject obj;
  obj.insert("namespace","events");
  obj.insert("name", subscribe ? "subscribe" : "unsubscribe");
  obj.insert("id", "sysadm-client-event-auto");
  QString arg;
  if(event == DISPATCHER){ arg = "dispatcher"; }
  obj.insert("args", arg);
  sendSocketMessage(obj);
}

void sysadm_client::sendSocketMessage(QJsonObject msg){
  QJsonDocument doc(msg);
  SOCKET->sendTextMessage(doc.toJson(QJsonDocument::Compact));
}

//Simplification functions
QJsonObject sysadm_client::convertServerReply(QString reply){
  QJsonDocument doc = QJsonDocument::fromJson(reply.toUtf8());
  if(doc.isObject()){ return doc.object(); }
  else{ return QJsonObject(); }
}

// === PUBLIC SLOTS ===
// Communications with server (send message, get response via signal later)
void sysadm_client::communicate(QString ID, QString namesp, QString name, QJsonValue args){
  //Overloaded function for a request which needs assembly
  QJsonObject obj;
  obj.insert("namespace",namesp);
  obj.insert("name", name);
  obj.insert("id", ID);
  obj.insert("args", args);
  communicate(QList<QJsonObject>() << obj);
}

void sysadm_client::communicate(QJsonObject request){
  //Overloaded function for a single JSON request
  communicate(QList<QJsonObject>() << request);
}

void sysadm_client::communicate(QList<QJsonObject> requests){
  for(int i=0; i<requests.length(); i++){
    QString ID = requests[i].value("id").toString();
    if(ID.isEmpty()){
      qDebug() << "Malformed JSON request:" << requests[i];
      continue;
    }
    //Save this into the cache
    SENT.insert(ID, requests[i]);
    if(BACK.contains(ID)){ BACK.remove(ID); }
    PENDING << ID;
    //Now send off the message
    if(SOCKET->isValid()){ sendSocketMessage(requests[i]); }
  }
}

// === PRIVATE SLOTS ===
//Socket signal/slot connections
void sysadm_client::socketConnected(){ //Signal: connected()
  keepActive = true; //got a valid connection - try to keep this open automatically
  num_fail = 0; //reset fail counter - got a valid connection
  emit clientConnected();
  performAuth(cuser, cpass);
  cuser.clear(); cpass.clear(); //just to ensure no trace left in memory
}

void sysadm_client::socketClosed(){ //Signal: disconnected()
  if(keepActive && num_fail < FAIL_MAX){
    //Socket closed due to timeout?
    // Go ahead and re-open it if possible with the last-used settings/auth
    num_fail++;
    setupSocket();
  }else{
    num_fail = 0; //reset back to nothing
    emit clientDisconnected();
    //Server cache is now invalid - completely lost connection
    SENT.clear(); BACK.clear(); PENDING.clear();
  }
}

void sysadm_client::socketSslErrors(const QList<QSslError>&errlist){ //Signal: sslErrors()
  qWarning() << "SSL Errors Detected:" << errlist.length();
  //SOCKET->ignoreSslErrors(QList<QSslError>() << QSslError(QSslError::SelfSignedCertificate) << QSslError(QSslError::HostNameMismatch) );
  QList<QSslError> ignored;
  for(int i=0; i< errlist.length(); i++){
    if(errlist[i].error()==QSslError::SelfSignedCertificate || errlist[i].error()==QSslError::HostNameMismatch ){
      qDebug() << " - (IGNORED) " << errlist[i].errorString();
      ignored << errlist[i];
    }else{
      qWarning() << " - " << errlist[i].errorString();
    }
  }
  if(!ignored.isEmpty()){
    qDebug() << "Ignoring errors:";
    SOCKET->ignoreSslErrors(ignored);
  }
}

void sysadm_client::socketError(QAbstractSocket::SocketError err){ //Signal:: error()
  qWarning() << "Socket Error detected:" << err;
  if(err==13){qWarning() << " - SSL Handshake Failed"; }
  qWarning() << " - Final websocket error:" << SOCKET->errorString();
}
//void sysadm_client::socketProxyAuthRequired(const QNetworkProxy &proxy, QAuthenticator *auth); //Signal: proxyAuthenticationRequired()

// - Main message input parsing
void sysadm_client::socketMessage(QString msg){ //Signal: textMessageReceived()
  qDebug() << "New Reply From Server:" << msg;
  //Convert this into a JSON object
  QJsonObject obj = convertServerReply(msg);
  QString ID = obj.value("id").toString();
  QString namesp = obj.value("namespace").toString();
  QString name = obj.value("name").toString();
  //Still need to add some parsing to the return message
  if(ID=="sysadm-client-auth-auto"){
    //Reply to automated auth system
    if(name=="error"){
      emit clientUnauthorized();
    }else{
      QJsonValue args = obj.value("args");
      if(args.isArray()){
	  cauthkey = args.toArray().first().toString();
	  emit clientAuthorized();
	  //Now automatically re-subscribe to events as needed
	  for(int i=0; i<events.length(); i++){ sendEventSubscription(events[i]); }
      }
    }
  }else if(ID=="sysadm-client-event-auto"){
    //Reply to automated event subscription - don't need to save this
  }else if(namesp=="events"){
    //Event notification - not tied to any particular request
    if(name=="dispatcher"){ emit DispatcherEvent(obj.value("args")); }
  }else{
    //Now save this message into the cache for use later (if not an auth reply)
    if(!ID.isEmpty()){
      PENDING.removeAll(ID);
      BACK.insert(ID, obj);
    }
    emit newReply(ID, name, namesp, obj.value("args"));
  }
}
	<commit_msg>Get the SSL stuff sorted out with a workaround for the ignored errors settings. Now the client can successfully connect to the server.<commit_after>//===========================================
//  PC-BSD source code
//  Copyright (c) 2016, PC-BSD Software/iXsystems
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================
#include "sysadm-client.h"
#include <QSslConfiguration>
#include <QJsonArray>
#include <QTimer>

// === PUBLIC ===
sysadm_client::sysadm_client(){
  SOCKET = new QWebSocket("sysadm-client", QWebSocketProtocol::VersionLatest, this);
    SOCKET->setSslConfiguration(QSslConfiguration::defaultConfiguration());
    //SOCKET->ignoreSslErrors();
    //use the new Qt5 connection syntax for compile time checks that connections are valid
    connect(SOCKET, &QWebSocket::connected, this, &sysadm_client::socketConnected);
    connect(SOCKET, &QWebSocket::disconnected, this, &sysadm_client::socketClosed);
    connect(SOCKET, &QWebSocket::textMessageReceived, this, &sysadm_client::socketMessage);
    //Old connect syntax for the "error" signal (special note about issues in the docs)
    connect(SOCKET, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)) );
    connect(SOCKET, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(socketSslErrors(const QList<QSslError>&)) );
  keepActive=false; //not setup yet
  settings = new QSettings("PC-BSD","sysadm-client", this);
}

sysadm_client::~sysadm_client(){

}

// Overall Connection functions (start/stop)
void sysadm_client::openConnection(QString user, QString pass, QString hostIP){
  cuser = user; cpass = pass; chost = hostIP;
  qDebug() << "Client: Setup connection:" << user << pass << hostIP;
  setupSocket();
}

void sysadm_client::openConnection(QString authkey, QString hostIP){
  cauthkey = authkey; chost = hostIP;
  setupSocket();
}

void sysadm_client::closeConnection(){
  keepActive = false;
  //de-authorize the current auth token
  cauthkey.clear();
  performAuth();
  //Now close the connection
  SOCKET->close(QWebSocketProtocol::CloseCodeNormal, "sysadm-client closed");
}

// Connection Hosts Database Access
QStringList sysadm_client::knownHosts(){
  //Returns: <IP>::::<Name>
  QStringList hosts =settings->value("knownhosts",QStringList()).toStringList();
  for(int i=0; i<hosts.length(); i++){
    hosts[i].append("::::" + settings->value("hostnames/"+hosts[i],"").toString() );
  }
  return hosts;
}

void sysadm_client::saveHost(QString IP, QString name){
  QStringList hosts = settings->value("knownhosts",QStringList()).toStringList();
  hosts << IP;
  hosts.removeDuplicates();
  settings->setValue("knownhosts",hosts);
  settings->setValue("hostnames/"+IP,name);
}

void sysadm_client::removeHost(QString IP){
  QStringList hosts = settings->value("knownhosts",QStringList()).toStringList();
  hosts.removeAll(IP);
  settings->setValue("knownhosts",hosts);
  settings->remove("hostnames/"+IP);
}

// Register for Event Notifications (no notifications by default)
void sysadm_client::registerForEvents(EVENT_TYPE event, bool receive){
  bool set = events.contains(event);
  if( set && receive){ return; } //already registered
  else if(!set && !receive){ return; } //already unregistered
  else if(set){ events << event; }
  else{ events.removeAll(event); }
  //Since this can be setup before the socket is connected - see if we can send this message right away
  if(SOCKET->isValid()){
    sendEventSubscription(event, receive);
  }

}

// Messages which are still pending a response
QStringList sysadm_client::pending(){ return PENDING; } //returns only the "id" for each

// Fetch a message from the recent cache
QJsonObject sysadm_client::cachedRequest(QString id){
  if(SENT.contains(id)){ return SENT.value(id); }
  else{ return QJsonObject(); }
}

QJsonValue sysadm_client::cachedReply(QString id){
  if(BACK.contains(id)){ return BACK.value(id); }
  else{ return QJsonObject(); }
}

// === PRIVATE ===
//Functions to do the initial socket setup
void sysadm_client::setupSocket(){
  qDebug() << "Setup Socket:" << SOCKET->isValid();
  if(SOCKET->isValid()){ return; }
  //uses chost for setup
  // - assemble the host URL
  if(chost.contains("://")){ chost = chost.section("://",1,1); } //Chop off the custom http/ftp/other header (always need "wss://")
  QString url = "wss://"+chost;
  bool hasport = false;
  url.section(":",-1).toInt(&hasport); //check if the last piece of the url is a valid number
  //Could add a check for a valid port number as well - but that is a bit overkill right now
  if(!hasport){ url.append(":"+QString::number(WSPORTDEFAULT)); }
  qDebug() << " - URL:" << url;
  QTimer::singleShot(0,SOCKET, SLOT(ignoreSslErrors()) );
  SOCKET->open(QUrl(url));
    //QList<QSslError> ignored; ignored << QSslError(QSslError::SelfSignedCertificate) << QSslError(QSslError::HostNameMismatch);
    //SOCKET->ignoreSslErrors(ignored);
}

void sysadm_client::performAuth(QString user, QString pass){
  //uses cauthkey if empty inputs
  QJsonObject obj;
  obj.insert("namespace","rpc");
  obj.insert("id","sysadm-client-auth-auto");
  bool noauth = false;
  if(user.isEmpty() && pass.isEmpty()){
    if(cauthkey.isEmpty()){
      //Nothing to authenticate - de-auth the connection instead
      obj.insert("name","auth_clear");
      obj.insert("args","");
      noauth = true;
    }else{
      //Saved token authentication
      obj.insert("name","auth_token");
      QJsonObject arg;
	arg.insert("token",cauthkey);
      obj.insert("args", arg);
    }
  }else{
    //User/password authentication
    obj.insert("name","auth");
    QJsonObject arg;
      arg.insert("username",user);
      arg.insert("password",pass);
    obj.insert("args", arg);
  }
  sendSocketMessage(obj);
  if(noauth){ emit clientUnauthorized(); }
}

//Communication subroutines with the server (block until message comes back)
void sysadm_client::sendEventSubscription(EVENT_TYPE event, bool subscribe){
  QJsonObject obj;
  obj.insert("namespace","events");
  obj.insert("name", subscribe ? "subscribe" : "unsubscribe");
  obj.insert("id", "sysadm-client-event-auto");
  QString arg;
  if(event == DISPATCHER){ arg = "dispatcher"; }
  obj.insert("args", arg);
  sendSocketMessage(obj);
}

void sysadm_client::sendSocketMessage(QJsonObject msg){
  QJsonDocument doc(msg);
  SOCKET->sendTextMessage(doc.toJson(QJsonDocument::Compact));
}

//Simplification functions
QJsonObject sysadm_client::convertServerReply(QString reply){
  QJsonDocument doc = QJsonDocument::fromJson(reply.toUtf8());
  if(doc.isObject()){ return doc.object(); }
  else{ return QJsonObject(); }
}

// === PUBLIC SLOTS ===
// Communications with server (send message, get response via signal later)
void sysadm_client::communicate(QString ID, QString namesp, QString name, QJsonValue args){
  //Overloaded function for a request which needs assembly
  QJsonObject obj;
  obj.insert("namespace",namesp);
  obj.insert("name", name);
  obj.insert("id", ID);
  obj.insert("args", args);
  communicate(QList<QJsonObject>() << obj);
}

void sysadm_client::communicate(QJsonObject request){
  //Overloaded function for a single JSON request
  communicate(QList<QJsonObject>() << request);
}

void sysadm_client::communicate(QList<QJsonObject> requests){
  for(int i=0; i<requests.length(); i++){
    QString ID = requests[i].value("id").toString();
    if(ID.isEmpty()){
      qDebug() << "Malformed JSON request:" << requests[i];
      continue;
    }
    //Save this into the cache
    SENT.insert(ID, requests[i]);
    if(BACK.contains(ID)){ BACK.remove(ID); }
    PENDING << ID;
    //Now send off the message
    if(SOCKET->isValid()){ sendSocketMessage(requests[i]); }
  }
}

// === PRIVATE SLOTS ===
//Socket signal/slot connections
void sysadm_client::socketConnected(){ //Signal: connected()
  keepActive = true; //got a valid connection - try to keep this open automatically
  num_fail = 0; //reset fail counter - got a valid connection
  emit clientConnected();
  performAuth(cuser, cpass);
  cuser.clear(); cpass.clear(); //just to ensure no trace left in memory
}

void sysadm_client::socketClosed(){ //Signal: disconnected()
  if(keepActive && num_fail < FAIL_MAX){
    //Socket closed due to timeout?
    // Go ahead and re-open it if possible with the last-used settings/auth
    num_fail++;
    setupSocket();
  }else{
    num_fail = 0; //reset back to nothing
    emit clientDisconnected();
    //Server cache is now invalid - completely lost connection
    SENT.clear(); BACK.clear(); PENDING.clear();
  }
}

void sysadm_client::socketSslErrors(const QList<QSslError>&errlist){ //Signal: sslErrors()
  qWarning() << "SSL Errors Detected:" << errlist.length();
  QList<QSslError> ignored;
  for(int i=0; i< errlist.length(); i++){
    if(errlist[i].error()==QSslError::SelfSignedCertificate || errlist[i].error()==QSslError::HostNameMismatch ){
      qDebug() << " - (IGNORED) " << errlist[i].errorString();
      ignored << errlist[i];
    }else{
      qWarning() << " - " << errlist[i].errorString();
    }
  }
  if(ignored.length() != errlist.length()){
    SOCKET->close(); //SSL errors - close the connection
  }
}

void sysadm_client::socketError(QAbstractSocket::SocketError err){ //Signal:: error()
  qWarning() << "Socket Error detected:" << err;
  if(err==QAbstractSocket::SslHandshakeFailedError){qWarning() << " - SSL Handshake Failed"; }
  qWarning() << " - Final websocket error:" << SOCKET->errorString();
}
//void sysadm_client::socketProxyAuthRequired(const QNetworkProxy &proxy, QAuthenticator *auth); //Signal: proxyAuthenticationRequired()

// - Main message input parsing
void sysadm_client::socketMessage(QString msg){ //Signal: textMessageReceived()
  qDebug() << "New Reply From Server:" << msg;
  //Convert this into a JSON object
  QJsonObject obj = convertServerReply(msg);
  QString ID = obj.value("id").toString();
  QString namesp = obj.value("namespace").toString();
  QString name = obj.value("name").toString();
  //Still need to add some parsing to the return message
  if(ID=="sysadm-client-auth-auto"){
    //Reply to automated auth system
    if(name=="error"){
      emit clientUnauthorized();
    }else{
      QJsonValue args = obj.value("args");
      if(args.isArray()){
	  cauthkey = args.toArray().first().toString();
	  emit clientAuthorized();
	  //Now automatically re-subscribe to events as needed
	  for(int i=0; i<events.length(); i++){ sendEventSubscription(events[i]); }
      }
    }
  }else if(ID=="sysadm-client-event-auto"){
    //Reply to automated event subscription - don't need to save this
  }else if(namesp=="events"){
    //Event notification - not tied to any particular request
    if(name=="dispatcher"){ emit DispatcherEvent(obj.value("args")); }
  }else{
    //Now save this message into the cache for use later (if not an auth reply)
    if(!ID.isEmpty()){
      PENDING.removeAll(ID);
      BACK.insert(ID, obj);
    }
    emit newReply(ID, name, namesp, obj.value("args"));
  }
}
	<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// rule_test.cpp
//
// Identification: test/optimizer/rule_test.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "common/harness.h"

#define private public

#include "optimizer/operator_expression.h"
#include "optimizer/operators.h"
#include "optimizer/optimizer.h"
#include "optimizer/rule.h"
#include "optimizer/rule_impls.h"

#include "catalog/catalog.h"
#include "common/logger.h"
#include "common/statement.h"
#include "executor/create_executor.h"
#include "executor/delete_executor.h"
#include "executor/insert_executor.h"
#include "executor/plan_executor.h"
#include "executor/update_executor.h"
#include "optimizer/simple_optimizer.h"
#include "parser/parser.h"
#include "planner/create_plan.h"
#include "planner/delete_plan.h"
#include "planner/insert_plan.h"
#include "planner/update_plan.h"

namespace peloton {
namespace test {

//===--------------------------------------------------------------------===//
// Binding Tests
//===--------------------------------------------------------------------===//

using namespace optimizer;

class RuleTests : public PelotonTest {};

TEST_F(RuleTests, SimpleRuleApplyTest) {
  // Build op plan node to match rule
  auto left_get = std::make_shared<OperatorExpression>(LogicalGet::make(0));
  auto right_get = std::make_shared<OperatorExpression>(LogicalGet::make(0));
  auto val = type::ValueFactory::GetBooleanValue(true);
  auto join = std::make_shared<OperatorExpression>(LogicalInnerJoin::make());
  join->PushChild(left_get);
  join->PushChild(right_get);

  // Setup rule
  InnerJoinCommutativity rule;

  EXPECT_TRUE(rule.Check(join));

  std::vector<std::shared_ptr<OperatorExpression>> outputs;
  rule.Transform(join, outputs);
  EXPECT_EQ(outputs.size(), 1);
}

// Test whether update stament will use index scan plan
TEST_F(RuleTests, UpdateDelWithIndexScanTest) {
  LOG_INFO("Bootstrapping...");
  catalog::Catalog::GetInstance()->CreateDatabase(DEFAULT_DB_NAME, nullptr);
  LOG_INFO("Bootstrapping completed!");

  // Create a table first
  auto& txn_manager = concurrency::TransactionManagerFactory::GetInstance();

  auto txn = txn_manager.BeginTransaction();
  LOG_INFO("Creating table");
  LOG_INFO(
      "Query: CREATE TABLE department_table(dept_id INT PRIMARY KEY,student_id "
      "INT, dept_name TEXT);");
  std::unique_ptr<Statement> statement;
  statement.reset(new Statement("CREATE",
                                "CREATE TABLE department_table(dept_id INT "
                                "PRIMARY KEY, student_id INT, dept_name "
                                "TEXT);"));

  auto& peloton_parser = parser::Parser::GetInstance();

  auto create_stmt = peloton_parser.BuildParseTree(
      "CREATE TABLE department_table(dept_id INT PRIMARY KEY, student_id INT, "
      "dept_name TEXT);");

  statement->SetPlanTree(
      optimizer::SimpleOptimizer::BuildPelotonPlanTree(create_stmt));

  std::vector<common::Value*> params;
  std::vector<ResultType> result;
  bridge::PlanExecutor::PrintPlan(statement->GetPlanTree().get(), "Plan");
  std::vector<int> result_format;
  result_format =
      std::move(std::vector<int>(statement->GetTupleDescriptor().size(), 0));
  bridge::peloton_status status = bridge::PlanExecutor::ExecutePlan(
      statement->GetPlanTree().get(), params, result, result_format);
  LOG_INFO("Statement executed. Result: %d", status.m_result);
  LOG_INFO("Table Created");
  txn_manager.CommitTransaction(txn);

  EXPECT_EQ(catalog::Catalog::GetInstance()
                ->GetDatabaseWithName(DEFAULT_DB_NAME)
                ->GetTableCount(),
            1);

  // Inserting a tuple end-to-end
  txn = txn_manager.BeginTransaction();
  LOG_INFO("Inserting a tuple...");
  LOG_INFO(
      "Query: INSERT INTO department_table(dept_id,student_id ,dept_name) "
      "VALUES (1,52,'hello_1');");
  statement.reset(new Statement("INSERT",
                                "INSERT INTO department_table(dept_id, "
                                "student_id, dept_name) VALUES "
                                "(1,52,'hello_1');"));

  auto insert_stmt = peloton_parser.BuildParseTree(
      "INSERT INTO department_table(dept_id,student_id,dept_name) VALUES "
      "(1,52,'hello_1');");

  statement->SetPlanTree(
      optimizer::SimpleOptimizer::BuildPelotonPlanTree(insert_stmt));

  result_format =
      std::move(std::vector<int>(statement->GetTupleDescriptor().size(), 0));
  status = bridge::PlanExecutor::ExecutePlan(statement->GetPlanTree().get(),
                                             params, result, result_format);
  LOG_INFO("Statement executed. Result: %d", status.m_result);
  LOG_INFO("Tuple inserted!");
  txn_manager.CommitTransaction(txn);

  // Now Create index
  txn = txn_manager.BeginTransaction();
  LOG_INFO("Creating and Index");
  LOG_INFO("Query: CREATE INDEX saif ON department_table (student_id);");
  statement.reset(new Statement(
      "CREATE", "CREATE INDEX saif ON department_table (student_id);"));

  auto update_stmt = peloton_parser.BuildParseTree(
      "CREATE INDEX saif ON department_table (student_id);");

  statement->SetPlanTree(
      optimizer::SimpleOptimizer::BuildPelotonPlanTree(update_stmt));

  result_format =
      std::move(std::vector<int>(statement->GetTupleDescriptor().size(), 0));
  status = bridge::PlanExecutor::ExecutePlan(statement->GetPlanTree().get(),
                                             params, result, result_format);
  LOG_INFO("Statement executed. Result: %d", status.m_result);
  LOG_INFO("INDEX CREATED!");
  txn_manager.CommitTransaction(txn);

  auto target_table_ = catalog::Catalog::GetInstance()->GetTableWithName(
      DEFAULT_DB_NAME, "department_table");
  // Expected 1 , Primary key index + created index
  EXPECT_EQ(target_table_->GetIndexCount(), 2);

  // Test update tuple with index scan
  txn = txn_manager.BeginTransaction();
  LOG_INFO("Updating a tuple...");
  LOG_INFO(
      "Query: UPDATE department_table SET dept_name = 'CS' WHERE student_id = 52");
  statement.reset(new Statement(
      "UPDATE",
      "UPDATE department_table SET dept_name = 'CS' WHERE student_id = 52"));
  LOG_INFO("Building parse tree...");
  update_stmt = peloton_parser.BuildParseTree(
      "UPDATE department_table SET dept_name = 'CS' WHERE student_id = 52");
  LOG_INFO("Building parse tree completed!");
  LOG_INFO("Building plan tree...");
  statement->SetPlanTree(
      optimizer::SimpleOptimizer::BuildPelotonPlanTree(update_stmt));
  LOG_INFO("Building plan tree completed!");
  planner::AbstractPlan *plan = statement->GetPlanTree().get();
  bridge::PlanExecutor::PrintPlan(statement->GetPlanTree().get(), "Plan");

  // Check scan plan
  ASSERT_FALSE(plan == nullptr);
  if (plan->GetPlanNodeType() == PLAN_NODE_TYPE_UPDATE) {
    auto& scanPlan = plan->GetChildren().front();
    EXPECT_EQ(scanPlan->GetPlanNodeType(), PLAN_NODE_TYPE_INDEXSCAN);
  }
  LOG_INFO("Executing plan...");
  result_format =
      std::move(std::vector<int>(statement->GetTupleDescriptor().size(), 0));
  status = bridge::PlanExecutor::ExecutePlan(statement->GetPlanTree().get(),
                                             params, result, result_format);
  LOG_INFO("Statement executed. Result: %d", status.m_result);
  LOG_INFO("Tuple Updated!");
  txn_manager.CommitTransaction(txn);

  // Test delete tuple with index scan
  txn = txn_manager.BeginTransaction();
  LOG_INFO("Deleting a tuple...");
  LOG_INFO("Query: DELETE FROM department_table WHERE student_id = 52");
  statement.reset(new Statement(
      "DELETE", "DELETE FROM department_table WHERE student_id = 52"));
  LOG_INFO("Building parse tree...");
  auto delete_stmt = peloton_parser.BuildParseTree(
      "DELETE FROM department_table WHERE student_id = 52");
  LOG_INFO("Building parse tree completed!");
  LOG_INFO("Building plan tree...");
  statement->SetPlanTree(
      optimizer::SimpleOptimizer::BuildPelotonPlanTree(delete_stmt));
  LOG_INFO("Building plan tree completed!");
  planner::AbstractPlan *delPlan = statement->GetPlanTree().get();
  bridge::PlanExecutor::PrintPlan(statement->GetPlanTree().get(), "Plan");

  // Check scan plan
  ASSERT_FALSE(delPlan == nullptr);
  if (delPlan->GetPlanNodeType() == PLAN_NODE_TYPE_DELETE) {
    auto& scanPlan = delPlan->GetChildren().front();
    EXPECT_EQ(scanPlan->GetPlanNodeType(), PLAN_NODE_TYPE_INDEXSCAN);
  }

  LOG_INFO("Executing plan...");
  result_format = std::move(std::vector<int>(0, 0));
  status = bridge::PlanExecutor::ExecutePlan(statement->GetPlanTree().get(),
                                             params, result, result_format);
  LOG_INFO("Statement executed. Result: %d", status.m_result);
  LOG_INFO("Tuple deleted!");
  txn_manager.CommitTransaction(txn);

  // free the database just created
  txn = txn_manager.BeginTransaction();
  catalog::Catalog::GetInstance()->DropDatabaseWithName(DEFAULT_DB_NAME, txn);
  txn_manager.CommitTransaction(txn);
}

} /* namespace test */
} /* namespace peloton */
<commit_msg>Remove index scan test in rule_test<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// rule_test.cpp
//
// Identification: test/optimizer/rule_test.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "common/harness.h"

#define private public

#include "optimizer/operator_expression.h"
#include "optimizer/operators.h"
#include "optimizer/optimizer.h"
#include "optimizer/rule.h"
#include "optimizer/rule_impls.h"

#include "catalog/catalog.h"
#include "common/logger.h"
#include "common/statement.h"
#include "executor/create_executor.h"
#include "executor/delete_executor.h"
#include "executor/insert_executor.h"
#include "executor/plan_executor.h"
#include "executor/update_executor.h"
#include "optimizer/simple_optimizer.h"
#include "parser/parser.h"
#include "planner/create_plan.h"
#include "planner/delete_plan.h"
#include "planner/insert_plan.h"
#include "planner/update_plan.h"

namespace peloton {
namespace test {

//===--------------------------------------------------------------------===//
// Binding Tests
//===--------------------------------------------------------------------===//

using namespace optimizer;

class RuleTests : public PelotonTest {};

TEST_F(RuleTests, SimpleRuleApplyTest) {
  // Build op plan node to match rule
  auto left_get = std::make_shared<OperatorExpression>(LogicalGet::make(0));
  auto right_get = std::make_shared<OperatorExpression>(LogicalGet::make(0));
  auto val = type::ValueFactory::GetBooleanValue(true);
  auto join = std::make_shared<OperatorExpression>(LogicalInnerJoin::make());
  join->PushChild(left_get);
  join->PushChild(right_get);

  // Setup rule
  InnerJoinCommutativity rule;

  EXPECT_TRUE(rule.Check(join));

  std::vector<std::shared_ptr<OperatorExpression>> outputs;
  rule.Transform(join, outputs);
  EXPECT_EQ(outputs.size(), 1);
}

} /* namespace test */
} /* namespace peloton */
<|endoftext|>


<commit_before>#include <vector>

#include "unittest/catch.h"

#include "core/pattern.h"
#include "core/task.h"

#include "plugins/pluginUtils.h"
#include "plugins/pmd.h"

#include "utils/utils.h"
#include "executorStub.h"
#include "optionsStub.h"

using std::vector;
using std::string;

using execHelper::config::SettingsNode;
using execHelper::core::Task;
using execHelper::core::TaskCollection;
using execHelper::core::Pattern;
using execHelper::plugins::Pmd;

using execHelper::test::OptionsStub;
using execHelper::test::utils::Patterns;
using execHelper::test::utils::PATTERN1;
using execHelper::test::utils::PATTERN2;
using execHelper::test::utils::PATTERNS;
using execHelper::test::utils::PATTERN_KEYS;
using execHelper::test::utils::copyAndAppend;
using execHelper::test::utils::createPatternCombination;
using execHelper::core::test::ExecutorStub;

namespace {
    const string pmdConfigKey("pmd");
    const string PLUGIN_CONFIG_KEY("pmd");
    const string EXEC_CONFIG_KEY("exec");
    const string TOOL_CONFIG_KEY("tool");
    const string MINIMUM_TOKENS_CONFIG_KEY("minimum-tokens");
    const string FILES_CONFIG_KEY("files");
    const string LANGUAGE_CONFIG_KEY("language");
}

namespace execHelper { namespace plugins { namespace test {
    SCENARIO("Test the default options of the pmd plugin", "[plugins][pmd]") {
        GIVEN("A default configuration and the plugin") {
            Pmd plugin;

            Task task;
            const OptionsStub options;

            WHEN("We call the plugin") {
                bool returnCode = plugin.apply("random-command", task, options);

                THEN("The call should fail") {
                    REQUIRE_FALSE(returnCode);
                }
            }
        }
    }

    SCENARIO("Test the mandatory options of the pmd plugin", "[plugins][pmd]") {
        GIVEN("The respective configuration and the plugin") {
            const string command("pmd-command");

            OptionsStub options;
            SettingsNode& rootSettings = options.m_settings;

            Pmd plugin;
            Task task;

            WHEN("We add the tool config parameter") {
                AND_WHEN("We use a general parameter") {
                    rootSettings.add({pmdConfigKey, "tool"}, "tool");
                }
                AND_WHEN("We use a specific parameter") {
                    rootSettings.add({pmdConfigKey, command, "tool"}, "tool");
                }

                THEN_WHEN("We apply the plugin") {
                    bool returnCode = plugin.apply(command, task, options);

                    THEN_CHECK("That the apply succeeds") {
                        REQUIRE_FALSE(returnCode);
                    }
                }
            }

            WHEN("We add the exec config parameter") {
                THEN("As a general parameter") {
                    rootSettings.add({pmdConfigKey, "exec"}, "pmd.sh");
                }
                THEN("As a specific parameter") {
                    rootSettings.add({pmdConfigKey, command, "exec"}, "pmd.sh");
                }
                REQUIRE_FALSE(plugin.apply(command, task, options));
            }

            WHEN("We add all mandatory config parameters and apply command ") {
                THEN("As a general command") {
                    rootSettings.add({pmdConfigKey, "tool"}, "tool");
                    rootSettings.add({pmdConfigKey, "exec"}, "pmd.sh");
                }
                THEN("As a specific command") {
                    rootSettings.add({pmdConfigKey, command, "tool"}, "tool");
                    rootSettings.add({pmdConfigKey, command, "exec"}, "pmd.sh");
                }

                REQUIRE(plugin.apply(command, task, options));

                ExecutorStub::TaskQueue actualTasks;
                Task actualTask({"pmd.sh", "tool"});
                actualTasks.emplace_back(actualTask);
                REQUIRE(actualTasks == options.m_executor.getExecutedTasks());
            }
        }
    }

    SCENARIO("Make combinations of different configurations for the pmd plugin", "[plugins][pmd]") {
        MAKE_COMBINATIONS("Of several settings") {
            const string command("pmd-command");

            OptionsStub options;
            for(const auto& pattern : PATTERNS) {
                options.m_patternsHandler->addPattern(pattern);
            }

            SettingsNode& rootSettings = options.m_settings;
            rootSettings.add({PLUGIN_CONFIG_KEY, "patterns"}, {PATTERN1.getKey(), PATTERN2.getKey()});

            // Add the settings of an other command to make sure we take the expected ones
            const string otherCommandKey("other-command");

            Pmd plugin;
            Task task;

            Task expectedTask;
            TaskCollection exec({"pmd.sh"});
            TaskCollection tool({"tool1"});
            TaskCollection minimumTokens;
            TaskCollection files;
            TaskCollection verbosity;
            TaskCollection language;
            TaskCollection commandLine;

            SettingsNode::SettingsKeys baseSettingsKeys = {PLUGIN_CONFIG_KEY};
            SettingsNode::SettingsKeys otherBaseSettingsKeys = {PLUGIN_CONFIG_KEY, otherCommandKey};

            COMBINATIONS("Toggle between general and specific command settings") {
                baseSettingsKeys.push_back(command);
            }

            rootSettings.add(copyAndAppend(otherBaseSettingsKeys, EXEC_CONFIG_KEY), "other-exec");
            rootSettings.add(copyAndAppend(otherBaseSettingsKeys, TOOL_CONFIG_KEY), "other-tool");

            COMBINATIONS("Switch off verbosity") {
                options.m_verbosity = false;
            }

            COMBINATIONS("Switch on verbosity") {
                options.m_verbosity = true;
                verbosity.emplace_back("-verbose");
            }

            COMBINATIONS("Switch on the cpd tool") {
                tool.clear();
                tool = {"cpd"};
            }

            COMBINATIONS("Switch on minimum tokens") {
                const string minimumTokensValue("100");
                rootSettings.add(copyAndAppend(baseSettingsKeys, MINIMUM_TOKENS_CONFIG_KEY), minimumTokensValue);

                if(tool[0] == "cpd") {
                    minimumTokens.emplace_back("--minimum-tokens");
                    minimumTokens.emplace_back("100");
                }
            }

            COMBINATIONS("Switch on files") {
                const vector<string> filesValue({"file1", "file2", "file*"});
                rootSettings.add(copyAndAppend(baseSettingsKeys, FILES_CONFIG_KEY), filesValue);
                rootSettings.add(copyAndAppend(otherBaseSettingsKeys, FILES_CONFIG_KEY), "other-file");

                if(tool[0] == "cpd") {
                    for(const auto& file : filesValue) {
                        files.emplace_back("--files");
                        files.emplace_back(file);
                    }
                }
            }

            COMBINATIONS("Add a language") {
                const string languageValue("language1");
                language.push_back("--language");
                language.push_back(languageValue);
                rootSettings.add(copyAndAppend(baseSettingsKeys, LANGUAGE_CONFIG_KEY), languageValue);
                rootSettings.add(copyAndAppend(otherBaseSettingsKeys, LANGUAGE_CONFIG_KEY), "other-language");
            }

            COMBINATIONS("Add a command line") {
                commandLine = {"{" + PATTERN2.getKey() + "}", "{" + PATTERN2.getKey() + "}"};
                rootSettings.add(copyAndAppend(baseSettingsKeys, "command-line"), commandLine);
                rootSettings.add(copyAndAppend(otherBaseSettingsKeys, "command-line"), "--some-command");
            }

            rootSettings.add(copyAndAppend(baseSettingsKeys, EXEC_CONFIG_KEY), exec);
            rootSettings.add(copyAndAppend(baseSettingsKeys, TOOL_CONFIG_KEY), tool);

            expectedTask.append(exec);
            expectedTask.append(tool);
            expectedTask.append(minimumTokens);
            expectedTask.append(files);
            expectedTask.append(language);
            expectedTask.append(verbosity);
            expectedTask.append(commandLine);

            ExecutorStub::TaskQueue expectedTasks;
            for(const std::map<string, string>& target : options.makePatternPermutator(PATTERN_KEYS)) {
                Task replacedExpectedTask = replacePatternCombinations(expectedTask, target);
                expectedTasks.emplace_back(replacedExpectedTask);
            }

            bool returnCode = plugin.apply(command, task, options);
            THEN_CHECK("It should succeed") {
                REQUIRE(returnCode);
            }

            THEN_CHECK("It called the right commands") {
                REQUIRE(expectedTasks == options.m_executor.getExecutedTasks());
            }

        }
    }
} } }
<commit_msg>Fixed remarks of clang-tidy<commit_after>#include <vector>

#include "unittest/catch.h"

#include "core/pattern.h"
#include "core/task.h"

#include "plugins/pluginUtils.h"
#include "plugins/pmd.h"

#include "utils/utils.h"
#include "executorStub.h"
#include "optionsStub.h"

using std::vector;
using std::string;

using execHelper::config::SettingsNode;
using execHelper::core::Task;
using execHelper::core::TaskCollection;
using execHelper::plugins::Pmd;

using execHelper::test::OptionsStub;
using execHelper::test::utils::Patterns;
using execHelper::test::utils::PATTERN1;
using execHelper::test::utils::PATTERN2;
using execHelper::test::utils::PATTERNS;
using execHelper::test::utils::PATTERN_KEYS;
using execHelper::test::utils::copyAndAppend;
using execHelper::core::test::ExecutorStub;

namespace {
    const string pmdConfigKey("pmd");
    const string PLUGIN_CONFIG_KEY("pmd");
    const string EXEC_CONFIG_KEY("exec");
    const string TOOL_CONFIG_KEY("tool");
    const string MINIMUM_TOKENS_CONFIG_KEY("minimum-tokens");
    const string FILES_CONFIG_KEY("files");
    const string LANGUAGE_CONFIG_KEY("language");
}

namespace execHelper { namespace plugins { namespace test {
    SCENARIO("Test the default options of the pmd plugin", "[plugins][pmd]") {
        GIVEN("A default configuration and the plugin") {
            Pmd plugin;

            Task task;
            const OptionsStub options;

            WHEN("We call the plugin") {
                bool returnCode = plugin.apply("random-command", task, options);

                THEN("The call should fail") {
                    REQUIRE_FALSE(returnCode);
                }
            }
        }
    }

    SCENARIO("Test the mandatory options of the pmd plugin", "[plugins][pmd]") {
        GIVEN("The respective configuration and the plugin") {
            const string command("pmd-command");

            OptionsStub options;
            SettingsNode& rootSettings = options.m_settings;

            Pmd plugin;
            Task task;

            WHEN("We add the tool config parameter") {
                AND_WHEN("We use a general parameter") {
                    rootSettings.add({pmdConfigKey, "tool"}, "tool");
                }
                AND_WHEN("We use a specific parameter") {
                    rootSettings.add({pmdConfigKey, command, "tool"}, "tool");
                }

                THEN_WHEN("We apply the plugin") {
                    bool returnCode = plugin.apply(command, task, options);

                    THEN_CHECK("That the apply succeeds") {
                        REQUIRE_FALSE(returnCode);
                    }
                }
            }

            WHEN("We add the exec config parameter") {
                THEN("As a general parameter") {
                    rootSettings.add({pmdConfigKey, "exec"}, "pmd.sh");
                }
                THEN("As a specific parameter") {
                    rootSettings.add({pmdConfigKey, command, "exec"}, "pmd.sh");
                }
                REQUIRE_FALSE(plugin.apply(command, task, options));
            }

            WHEN("We add all mandatory config parameters and apply command ") {
                THEN("As a general command") {
                    rootSettings.add({pmdConfigKey, "tool"}, "tool");
                    rootSettings.add({pmdConfigKey, "exec"}, "pmd.sh");
                }
                THEN("As a specific command") {
                    rootSettings.add({pmdConfigKey, command, "tool"}, "tool");
                    rootSettings.add({pmdConfigKey, command, "exec"}, "pmd.sh");
                }

                REQUIRE(plugin.apply(command, task, options));

                ExecutorStub::TaskQueue actualTasks;
                Task actualTask({"pmd.sh", "tool"});
                actualTasks.emplace_back(actualTask);
                REQUIRE(actualTasks == options.m_executor.getExecutedTasks());
            }
        }
    }

    SCENARIO("Make combinations of different configurations for the pmd plugin", "[plugins][pmd]") {
        MAKE_COMBINATIONS("Of several settings") {
            const string command("pmd-command");

            OptionsStub options;
            for(const auto& pattern : PATTERNS) {
                options.m_patternsHandler->addPattern(pattern);
            }

            SettingsNode& rootSettings = options.m_settings;
            rootSettings.add({PLUGIN_CONFIG_KEY, "patterns"}, {PATTERN1.getKey(), PATTERN2.getKey()});

            // Add the settings of an other command to make sure we take the expected ones
            const string otherCommandKey("other-command");

            Pmd plugin;
            Task task;

            Task expectedTask;
            TaskCollection exec({"pmd.sh"});
            TaskCollection tool({"tool1"});
            TaskCollection minimumTokens;
            TaskCollection files;
            TaskCollection verbosity;
            TaskCollection language;
            TaskCollection commandLine;

            SettingsNode::SettingsKeys baseSettingsKeys = {PLUGIN_CONFIG_KEY};
            SettingsNode::SettingsKeys otherBaseSettingsKeys = {PLUGIN_CONFIG_KEY, otherCommandKey};

            COMBINATIONS("Toggle between general and specific command settings") {
                baseSettingsKeys.push_back(command);
            }

            rootSettings.add(copyAndAppend(otherBaseSettingsKeys, EXEC_CONFIG_KEY), "other-exec");
            rootSettings.add(copyAndAppend(otherBaseSettingsKeys, TOOL_CONFIG_KEY), "other-tool");

            COMBINATIONS("Switch off verbosity") {
                options.m_verbosity = false;
            }

            COMBINATIONS("Switch on verbosity") {
                options.m_verbosity = true;
                verbosity.emplace_back("-verbose");
            }

            COMBINATIONS("Switch on the cpd tool") {
                tool.clear();
                tool = {"cpd"};
            }

            COMBINATIONS("Switch on minimum tokens") {
                const string minimumTokensValue("100");
                rootSettings.add(copyAndAppend(baseSettingsKeys, MINIMUM_TOKENS_CONFIG_KEY), minimumTokensValue);

                if(tool[0] == "cpd") {
                    minimumTokens.emplace_back("--minimum-tokens");
                    minimumTokens.emplace_back("100");
                }
            }

            COMBINATIONS("Switch on files") {
                const vector<string> filesValue({"file1", "file2", "file*"});
                rootSettings.add(copyAndAppend(baseSettingsKeys, FILES_CONFIG_KEY), filesValue);
                rootSettings.add(copyAndAppend(otherBaseSettingsKeys, FILES_CONFIG_KEY), "other-file");

                if(tool[0] == "cpd") {
                    for(const auto& file : filesValue) {
                        files.emplace_back("--files");
                        files.emplace_back(file);
                    }
                }
            }

            COMBINATIONS("Add a language") {
                const string languageValue("language1");
                language.emplace_back("--language");
                language.push_back(languageValue);
                rootSettings.add(copyAndAppend(baseSettingsKeys, LANGUAGE_CONFIG_KEY), languageValue);
                rootSettings.add(copyAndAppend(otherBaseSettingsKeys, LANGUAGE_CONFIG_KEY), "other-language");
            }

            COMBINATIONS("Add a command line") {
                commandLine = {"{" + PATTERN2.getKey() + "}", "{" + PATTERN2.getKey() + "}"};
                rootSettings.add(copyAndAppend(baseSettingsKeys, "command-line"), commandLine);
                rootSettings.add(copyAndAppend(otherBaseSettingsKeys, "command-line"), "--some-command");
            }

            rootSettings.add(copyAndAppend(baseSettingsKeys, EXEC_CONFIG_KEY), exec);
            rootSettings.add(copyAndAppend(baseSettingsKeys, TOOL_CONFIG_KEY), tool);

            expectedTask.append(exec);
            expectedTask.append(tool);
            expectedTask.append(minimumTokens);
            expectedTask.append(files);
            expectedTask.append(language);
            expectedTask.append(verbosity);
            expectedTask.append(commandLine);

            ExecutorStub::TaskQueue expectedTasks;
            for(const std::map<string, string>& target : options.makePatternPermutator(PATTERN_KEYS)) {
                Task replacedExpectedTask = replacePatternCombinations(expectedTask, target);
                expectedTasks.emplace_back(replacedExpectedTask);
            }

            bool returnCode = plugin.apply(command, task, options);
            THEN_CHECK("It should succeed") {
                REQUIRE(returnCode);
            }

            THEN_CHECK("It called the right commands") {
                REQUIRE(expectedTasks == options.m_executor.getExecutedTasks());
            }

        }
    }
} } }
<|endoftext|>


<commit_before><commit_msg>added more outputs to diamond<commit_after><|endoftext|>


<commit_before><commit_msg>Add whitespace between the string literal and the macro<commit_after><|endoftext|>


<commit_before>/******************************************************************************
*	Main script for the 2017 RoboFishy Scripps AUV
******************************************************************************/

#include "Mapper.h"

// Multithreading
#include <pthread.h>
#include <sched.h>
#include <unistd.h>

// Sampling Values
#define SAMPLE_RATE 200 // sample rate of main control loop (Hz)
#define DT 0.005				// timestep; make sure this is equal to 1/SAMPLE_RATE!

// Conversion Factors
#define UNITS_KPA 0.1		// converts pressure from mbar to kPa

/******************************************************************************
* Controller Gains
******************************************************************************/

// Yaw Controller
#define KP_YAW 0.01
#define KI_YAW 0
#define KD_YAW 1

// Depth Controller
#define KP_DEPTH 0
#define KI_DEPTH 0
#define KD_DEPTH 0

// Saturation Constants
#define YAW_SAT 1			// upper limit of yaw controller
#define DEPTH_SAT 1		// upper limit of depth controller
#define INT_SAT 10		// upper limit of integral windup
#define DINT_SAT 10		// upper limit of depth integral windup

// Fluid Densities in kg/m^3
#define DENSITY_FRESHWATER 997
#define DENSITY_SALTWATER 1029

// Acceleration Due to Gravity in m/s^2
#define GRAVITY 9.81

// Depth Start Value
#define DEPTH_START 50 // starting depth (mm)

// Stop Timer
#define STOP_TIME 10		// seconds

// Leak Sensor Inpu and Power Pin
#define LEAKPIN 27		// connected to GPIO 27
#define LEAKPOWERPIN 17 // providing Vcc to leak board

/******************************************************************************
 * Declare Threads
******************************************************************************/

void *navigation_thread(void* arg);
void *depth_thread(void* arg);
void *safety_thread(void* arg);
void *userInterface(void* arg);

/******************************************************************************
 * Global Variables
******************************************************************************/

// Holds the setpoint data structure with current setpoints
//setpoint_t setpoint;

// Holds the latest pressure value from the MS5837 pressure sensor
ms5837_t ms5837;

// Holds the latest temperature value from the temperature temperature sensor
float temperature;

// Holds the constants and latest errors of the yaw pid controller
pid_data_t yaw_pid;

// Holds the constants and latest errors of the depth pid controller
pid_data_t depth_pid;

// Motor channels
int motor_channels[] = {CHANNEL_1, CHANNEL_2, CHANNEL_3};

// Ignoring sstate
float depth = 0;

// setmotor intialization
float portmotorspeed = 0;
float starmotorspeed = 0;

// Start time for stop timer
time_t start;

/******************************************************************************
* Main Function
******************************************************************************/

int main()
{
	// capture ctrl+c and exit
	signal(SIGINT, ctrl_c);

	// Set up RasPi GPIO pins through wiringPi
	wiringPiSetupGpio();

	// Check if AUV is initialized correctly
	if( initialize_sensors() < 0 )
	{
		return -1;
	}
	printf("\nAll components are initialized\n");
	substate.mode = INITIALIZING;
  substate.laserarmed = ARMED;

	printf("Starting Threads\n");
	initializeTAttr();

	// Thread handles
	pthread_t navigationThread;
	pthread_t depthThread;
	//pthread_t safetyThread;
	//pthread_t disarmlaserThread;
	pthread_t uiThread;

	// Create threads using modified attributes
	//pthread_create (&disarmlaserThread, &tattrlow, disarmLaser, NULL);
	//pthread_create (&safetyThread, &tattrlow, safety_thread, NULL);
	pthread_create (&depthThread, &tattrmed, depth_thread, NULL);
	pthread_create (&navigationThread, &tattrmed, navigation_thread, NULL);
	pthread_create (&uiThread, &tattrmed, userInterface, NULL);

  // Destroy the thread attributes
 	destroyTAttr();

  printf("Threads started\n");

	// Start timer!
	start = time(0);

	// Run main while loop, wait until it's time to stop
	while(substate.mode != STOPPED)
	{
		// Check if we've passed the stop time
		if(difftime(time(0),start) > STOP_TIME)
			substate.mode = PAUSED;

		// Sleep a little
		auv_usleep(100000);
	}

	// Exit cleanly
	cleanup_auv();
	return 0;
}

/******************************************************************************
* Depth Thread
*
* For Recording Depth & Determining If AUV is in Water or not
******************************************************************************/

void *depth_thread(void* arg)
{
	printf("Depth Thread Started\n");

	while(substate.mode!=STOPPED)
	{
	  // Read pressure values
		ms5837 = read_pressure_fifo();

		// read IMU values from fifo file
		substate.imu = read_imu_fifo();

    // Only print while RUNNING
    if(substate.mode == RUNNING)
    {
      printf("\nCurrent Depth:\t %.3f m, Current water temp:\t %.3f C\n",
              ms5837.depth, ms5837.water_temp);

      printf("Current battery temp:\t %.2f\n", read_temp_fifo());

      // Write IMU data
      printf("\nYaw: %5.2f Roll: %5.2f Pitch: %5.2f p: %5.2f q: %5.2f r: %5.2f \nSys: %i Gyro: "
        "%i Accel: %i Mag: %i X_acc: %f Y_acc: %f Z_acc: %f\n ",
         substate.imu.yaw,	substate.imu.roll,	substate.imu.pitch,
         substate.imu.p, 		substate.imu.q,			substate.imu.r,
         substate.imu.sys,	substate.imu.gyro,	substate.imu.accel,
         substate.imu.mag,	substate.imu.x_acc,	substate.imu.y_acc,
         substate.imu.z_acc);
    }
		auv_usleep(1000000);
	}
	pthread_exit(NULL);
}//*/

/******************************************************************************
 * Navigation Thread
 *
 * For yaw control
 *****************************************************************************/
void *navigation_thread(void* arg)
{
	printf("Nav Thread Started\n");

	initialize_motors(motor_channels, HERTZ);

	float yaw = 0; 			  //Local variable for if statements
  float motorpercent;
  float basespeed = 0.2;

  ////////////////////////////////
  // Yaw Control Initialization //
  ////////////////////////////////
	yaw_pid.old 			= 0;	 	// Initialize old imu data
	yaw_pid.setpoint 	= 0;		// Initialize setpoint

	yaw_pid.derr = 0;
	yaw_pid.ierr = 0;					// Initialize error values
	yaw_pid.perr = 0;

	yaw_pid.kp = KP_YAW;
	yaw_pid.kd = KD_YAW;			// Initialize gain values
	yaw_pid.ki = KI_YAW;

	yaw_pid.isat = INT_SAT;		// Initialize saturation values
	yaw_pid.sat  = YAW_SAT;

	yaw_pid.dt   = DT;				// initialize time step

  //////////////////////////////////
  // Depth Control Initialization //
  //////////////////////////////////
	depth_pid.setpoint	= 2;		// Range-from-bottom setpoint (meters)
	depth_pid.old				= 0;		// Initialize old depth
	depth_pid.dt				= DT;		// Initialize depth controller time step

	depth_pid.kp = KP_DEPTH;
	depth_pid.kd = KD_DEPTH;		// Depth controller gain initialization
	depth_pid.ki = KI_DEPTH;

	depth_pid.perr = 0;
	depth_pid.ierr = 0;					// Initialize depth controller error values
	depth_pid.derr = 0;

	depth_pid.isat = INT_SAT;		// Depth controller saturation values
	depth_pid.sat  = DEPTH_SAT;

	while(substate.mode!=STOPPED)
	{
		// read IMU values from fifo file
		substate.imu = read_imu_fifo();

	  if (substate.imu.yaw < 180) // AUV pointed right
		{
			yaw = substate.imu.yaw;
		}
		else // AUV pointed left
		{
			yaw =(substate.imu.yaw-360);
		}

    // Only tell motors to run if we are RUNNING
    if( substate.mode == RUNNING)
    {
      //calculate yaw controller output
      motorpercent = marchPID(yaw_pid, yaw);

      // Set port and starboard
      portmotorspeed = basespeed + motorpercent;
      starmotorspeed = basespeed - motorpercent;

      // Set port motor
      set_motor(0, portmotorspeed);

      // Set starboard motor
      set_motor(1, starmotorspeed);

		} // end if RUNNING
		else if( substate.mode == PAUSED)
		{
		  // Stop horizontal motors
		  set_motor(0, 0);
		  set_motor(1, 0);

		  // Wipe integral error
		  yaw_pid.ierr = 0;

		  // Sleep a while (we're not doing anything anyways)
		  auv_usleep(100000);

		} // end if PAUSED

		// Sleep for 5 ms
		auv_usleep(DT);
	}

	// Turn motors off
	set_motor(0, 0);
	set_motor(1, 0);
	set_motor(2, 0);

	pthread_exit(NULL);
}//*/

/******************************************************************************
 * Safety Thread
 *
 * Shuts down AUV if vehicle goes belows 10m, temperature gets too high, or
 * water intrusion is detected
 *****************************************************************************/
/*void *safety_thread(void* arg)
{
	printf("Safety Thread Started\n");

	// Set up WiringPi for use // (not sure if actually needed)
	wiringPiSetup();

	// Leak detection pins
	pinMode(LEAKPIN, INPUT);					// set LEAKPIN as an INPUT
	pinMode(LEAKPOWERPIN, OUTPUT);		// set as output to provide Vcc
	digitalWrite(LEAKPOWERPIN, HIGH);	// write high to provide Vcc

	// Leak checking variables
	int leakState;	// holds the state (HIGH or LOW) of the LEAKPIN

	// Test if temp sensor reads anything
	temperature = read_temp_fifo();
	printf("Temperature: %f degC\n", temperature);

	while( substate.mode != STOPPED )
	{
		// Check if depth threshold has been exceeded
		if( substate.fdepth > DEPTH_STOP )
		{
			substate.mode = STOPPED;
			printf("We're too deep! Shutting down...\n");
			continue;
		}
		else
		{
			// We're still good
			substate.mode = RUNNING;
		}

		// Check temperature
		// Shut down AUV if housing temperature gets too high

		if( temperature > TEMP_STOP )
		{
			substate.mode = STOPPED;
			printf("It's too hot! Shutting down...\n");
			continue;
		}
		else
		{
			// We're still good
			substate.mode = RUNNING;
		}

		// Check for leak
		leakState = digitalRead(LEAKPIN);	// check the state of LEAKPIN
		if( leakState == HIGH )
		{
			substate.mode = STOPPED;
			printf("LEAK DETECTED! Shutting down...\n");
			continue;
		}
		else if (leakState == LOW)
		{
			// We're still good
			substate.mode = RUNNING;
		}

		// Check IMU accelerometer for collision (1+ g detected)
		if( (float)fabs(substate.imu.x_acc) > 1.0*GRAVITY
			|| (float)fabs(substate.imu.y_acc) > 1.0*GRAVITY
			|| (float)fabs(substate.imu.z_acc) > 1.0*GRAVITY )
		{
			substate.mode = STOPPED;
			printf("Collision detected. Shutting down...");
			continue;
		}
		else
		{
			// We're still good
			substate.mode = RUNNING;
		}

	}
    pthread_exit(NULL);

}//*/

/******************************************************************************
 * Logging Thread
 *
 * Logs the sensor output data into a file
 *****************************************************************************/
/*
PI_THREAD (logging_thread)
{
	while(substate.mode!=STOPPED){
		FILE *fd = fopen("log.txt", "a");
		char buffer[100] = {0};
		// add logging values to the next line
		sprintf(buffer, "%f %f %f %f %i %i %i %i %f %f %f %f\n",sstate.roll, sstate.pitch[0], sstate.yaw[0], sstate.depth[0],sstate.x[0],
		sstate.y[0], sstate.radius[0], setpoint.x - sstate.x[0], sstate.esc_out[0], sstate.esc_out[1], sstate.esc_out[2], sstate.esc_out[3]);
		fputs(buffer, fd);
		fclose(fd);
		//sleep for 100 ms

		usleep(100000);
	}
	return 0;
}
*/

/******************************************************************************
 * User Interface Thread
 * void* userInterface(void* arg)
 *
 * Interfaces with the user, asks for input
 *****************************************************************************/
 void* userInterface(void* arg)
 {
  // Declare local constant variables
  float _kp, _ki, _kd;

  // Wait a until everything is initialized before starting
  while(substate.mode == INITIALIZING)
  {
    // Waiting...
    auv_usleep(100000);
  }

  // Prompt user for values continuously until the program exits
  while(substate.mode != STOPPED)
  {
    // Prompt for kp
    std::cout << "Kp: ";
    std::cin >> _kp;

    // Prompt for ki
    std::cout << "Ki: ";
    std::cin >> _ki;

    // Prompt for kd
    std::cout << "Kd: ";
    std::cin >> _kd;

    // Give a newline
    std::cout << std::endl;

    // Reset gain values
    yaw_pid.kp = _kp;
    yaw_pid.ki = _ki;
    yaw_pid.kd = _kd;

    // Clear errors
    yaw_pid.perr = 0;
    yaw_pid.ierr = 0;
    yaw_pid.derr = 0;

    // Start RUNNING again
    substate.mode = RUNNING;

    // Restart timer!
	  start = time(0);

    // Aaaaaaand, WAIT!
    auv_usleep(10*1000000);
  }

  // Exit thread
  pthread_exit(NULL);
 }
<commit_msg>Set to running<commit_after>/******************************************************************************
*	Main script for the 2017 RoboFishy Scripps AUV
******************************************************************************/

#include "Mapper.h"

// Multithreading
#include <pthread.h>
#include <sched.h>
#include <unistd.h>

// Sampling Values
#define SAMPLE_RATE 200 // sample rate of main control loop (Hz)
#define DT 0.005				// timestep; make sure this is equal to 1/SAMPLE_RATE!

// Conversion Factors
#define UNITS_KPA 0.1		// converts pressure from mbar to kPa

/******************************************************************************
* Controller Gains
******************************************************************************/

// Yaw Controller
#define KP_YAW 0.01
#define KI_YAW 0
#define KD_YAW 1

// Depth Controller
#define KP_DEPTH 0
#define KI_DEPTH 0
#define KD_DEPTH 0

// Saturation Constants
#define YAW_SAT 1			// upper limit of yaw controller
#define DEPTH_SAT 1		// upper limit of depth controller
#define INT_SAT 10		// upper limit of integral windup
#define DINT_SAT 10		// upper limit of depth integral windup

// Fluid Densities in kg/m^3
#define DENSITY_FRESHWATER 997
#define DENSITY_SALTWATER 1029

// Acceleration Due to Gravity in m/s^2
#define GRAVITY 9.81

// Depth Start Value
#define DEPTH_START 50 // starting depth (mm)

// Stop Timer
#define STOP_TIME 10		// seconds

// Leak Sensor Inpu and Power Pin
#define LEAKPIN 27		// connected to GPIO 27
#define LEAKPOWERPIN 17 // providing Vcc to leak board

/******************************************************************************
 * Declare Threads
******************************************************************************/

void *navigation_thread(void* arg);
void *depth_thread(void* arg);
void *safety_thread(void* arg);
void *userInterface(void* arg);

/******************************************************************************
 * Global Variables
******************************************************************************/

// Holds the setpoint data structure with current setpoints
//setpoint_t setpoint;

// Holds the latest pressure value from the MS5837 pressure sensor
ms5837_t ms5837;

// Holds the latest temperature value from the temperature temperature sensor
float temperature;

// Holds the constants and latest errors of the yaw pid controller
pid_data_t yaw_pid;

// Holds the constants and latest errors of the depth pid controller
pid_data_t depth_pid;

// Motor channels
int motor_channels[] = {CHANNEL_1, CHANNEL_2, CHANNEL_3};

// Ignoring sstate
float depth = 0;

// setmotor intialization
float portmotorspeed = 0;
float starmotorspeed = 0;

// Start time for stop timer
time_t start;

/******************************************************************************
* Main Function
******************************************************************************/

int main()
{
	// capture ctrl+c and exit
	signal(SIGINT, ctrl_c);

	// Set up RasPi GPIO pins through wiringPi
	wiringPiSetupGpio();

	// Check if AUV is initialized correctly
	if( initialize_sensors() < 0 )
	{
		return -1;
	}
	printf("\nAll components are initialized\n");
	substate.mode = INITIALIZING;
  substate.laserarmed = ARMED;

	printf("Starting Threads\n");
	initializeTAttr();

	// Thread handles
	pthread_t navigationThread;
	pthread_t depthThread;
	//pthread_t safetyThread;
	//pthread_t disarmlaserThread;
	pthread_t uiThread;

	// Create threads using modified attributes
	//pthread_create (&disarmlaserThread, &tattrlow, disarmLaser, NULL);
	//pthread_create (&safetyThread, &tattrlow, safety_thread, NULL);
	pthread_create (&depthThread, &tattrmed, depth_thread, NULL);
	pthread_create (&navigationThread, &tattrmed, navigation_thread, NULL);
	pthread_create (&uiThread, &tattrmed, userInterface, NULL);

  // Destroy the thread attributes
 	destroyTAttr();

  printf("Threads started\n");

	// Start timer!
	start = time(0);

	// We're ready to run.
	substate.mode = RUNNING;

	// Run main while loop, wait until it's time to stop
	while(substate.mode != STOPPED)
	{
		// Check if we've passed the stop time
		if(difftime(time(0),start) > STOP_TIME)
			substate.mode = PAUSED;

		// Sleep a little
		auv_usleep(100000);
	}

	// Exit cleanly
	cleanup_auv();
	return 0;
}

/******************************************************************************
* Depth Thread
*
* For Recording Depth & Determining If AUV is in Water or not
******************************************************************************/

void *depth_thread(void* arg)
{
	printf("Depth Thread Started\n");

	while(substate.mode!=STOPPED)
	{
	  // Read pressure values
		ms5837 = read_pressure_fifo();

		// read IMU values from fifo file
		substate.imu = read_imu_fifo();

    // Only print while RUNNING
    if(substate.mode == RUNNING)
    {
      printf("\nCurrent Depth:\t %.3f m, Current water temp:\t %.3f C\n",
              ms5837.depth, ms5837.water_temp);

      printf("Current battery temp:\t %.2f\n", read_temp_fifo());

      // Write IMU data
      printf("\nYaw: %5.2f Roll: %5.2f Pitch: %5.2f p: %5.2f q: %5.2f r: %5.2f \nSys: %i Gyro: "
        "%i Accel: %i Mag: %i X_acc: %f Y_acc: %f Z_acc: %f\n ",
         substate.imu.yaw,	substate.imu.roll,	substate.imu.pitch,
         substate.imu.p, 		substate.imu.q,			substate.imu.r,
         substate.imu.sys,	substate.imu.gyro,	substate.imu.accel,
         substate.imu.mag,	substate.imu.x_acc,	substate.imu.y_acc,
         substate.imu.z_acc);
    }
		auv_usleep(1000000);
	}
	pthread_exit(NULL);
}//*/

/******************************************************************************
 * Navigation Thread
 *
 * For yaw control
 *****************************************************************************/
void *navigation_thread(void* arg)
{
	printf("Nav Thread Started\n");

	initialize_motors(motor_channels, HERTZ);

	float yaw = 0; 			  //Local variable for if statements
  float motorpercent;
  float basespeed = 0.2;

  ////////////////////////////////
  // Yaw Control Initialization //
  ////////////////////////////////
	yaw_pid.old 			= 0;	 	// Initialize old imu data
	yaw_pid.setpoint 	= 0;		// Initialize setpoint

	yaw_pid.derr = 0;
	yaw_pid.ierr = 0;					// Initialize error values
	yaw_pid.perr = 0;

	yaw_pid.kp = KP_YAW;
	yaw_pid.kd = KD_YAW;			// Initialize gain values
	yaw_pid.ki = KI_YAW;

	yaw_pid.isat = INT_SAT;		// Initialize saturation values
	yaw_pid.sat  = YAW_SAT;

	yaw_pid.dt   = DT;				// initialize time step

  //////////////////////////////////
  // Depth Control Initialization //
  //////////////////////////////////
	depth_pid.setpoint	= 2;		// Range-from-bottom setpoint (meters)
	depth_pid.old				= 0;		// Initialize old depth
	depth_pid.dt				= DT;		// Initialize depth controller time step

	depth_pid.kp = KP_DEPTH;
	depth_pid.kd = KD_DEPTH;		// Depth controller gain initialization
	depth_pid.ki = KI_DEPTH;

	depth_pid.perr = 0;
	depth_pid.ierr = 0;					// Initialize depth controller error values
	depth_pid.derr = 0;

	depth_pid.isat = INT_SAT;		// Depth controller saturation values
	depth_pid.sat  = DEPTH_SAT;

	while(substate.mode!=STOPPED)
	{
		// read IMU values from fifo file
		substate.imu = read_imu_fifo();

	  if (substate.imu.yaw < 180) // AUV pointed right
		{
			yaw = substate.imu.yaw;
		}
		else // AUV pointed left
		{
			yaw =(substate.imu.yaw-360);
		}

    // Only tell motors to run if we are RUNNING
    if( substate.mode == RUNNING)
    {
      //calculate yaw controller output
      motorpercent = marchPID(yaw_pid, yaw);

      // Set port and starboard
      portmotorspeed = basespeed + motorpercent;
      starmotorspeed = basespeed - motorpercent;

      // Set port motor
      set_motor(0, portmotorspeed);

      // Set starboard motor
      set_motor(1, starmotorspeed);

		} // end if RUNNING
		else if( substate.mode == PAUSED)
		{
		  // Stop horizontal motors
		  set_motor(0, 0);
		  set_motor(1, 0);

		  // Wipe integral error
		  yaw_pid.ierr = 0;

		  // Sleep a while (we're not doing anything anyways)
		  auv_usleep(100000);

		} // end if PAUSED

		// Sleep for 5 ms
		auv_usleep(DT);
	}

	// Turn motors off
	set_motor(0, 0);
	set_motor(1, 0);
	set_motor(2, 0);

	pthread_exit(NULL);
}//*/

/******************************************************************************
 * Safety Thread
 *
 * Shuts down AUV if vehicle goes belows 10m, temperature gets too high, or
 * water intrusion is detected
 *****************************************************************************/
/*void *safety_thread(void* arg)
{
	printf("Safety Thread Started\n");

	// Set up WiringPi for use // (not sure if actually needed)
	wiringPiSetup();

	// Leak detection pins
	pinMode(LEAKPIN, INPUT);					// set LEAKPIN as an INPUT
	pinMode(LEAKPOWERPIN, OUTPUT);		// set as output to provide Vcc
	digitalWrite(LEAKPOWERPIN, HIGH);	// write high to provide Vcc

	// Leak checking variables
	int leakState;	// holds the state (HIGH or LOW) of the LEAKPIN

	// Test if temp sensor reads anything
	temperature = read_temp_fifo();
	printf("Temperature: %f degC\n", temperature);

	while( substate.mode != STOPPED )
	{
		// Check if depth threshold has been exceeded
		if( substate.fdepth > DEPTH_STOP )
		{
			substate.mode = STOPPED;
			printf("We're too deep! Shutting down...\n");
			continue;
		}
		else
		{
			// We're still good
			substate.mode = RUNNING;
		}

		// Check temperature
		// Shut down AUV if housing temperature gets too high

		if( temperature > TEMP_STOP )
		{
			substate.mode = STOPPED;
			printf("It's too hot! Shutting down...\n");
			continue;
		}
		else
		{
			// We're still good
			substate.mode = RUNNING;
		}

		// Check for leak
		leakState = digitalRead(LEAKPIN);	// check the state of LEAKPIN
		if( leakState == HIGH )
		{
			substate.mode = STOPPED;
			printf("LEAK DETECTED! Shutting down...\n");
			continue;
		}
		else if (leakState == LOW)
		{
			// We're still good
			substate.mode = RUNNING;
		}

		// Check IMU accelerometer for collision (1+ g detected)
		if( (float)fabs(substate.imu.x_acc) > 1.0*GRAVITY
			|| (float)fabs(substate.imu.y_acc) > 1.0*GRAVITY
			|| (float)fabs(substate.imu.z_acc) > 1.0*GRAVITY )
		{
			substate.mode = STOPPED;
			printf("Collision detected. Shutting down...");
			continue;
		}
		else
		{
			// We're still good
			substate.mode = RUNNING;
		}

	}
    pthread_exit(NULL);

}//*/

/******************************************************************************
 * Logging Thread
 *
 * Logs the sensor output data into a file
 *****************************************************************************/
/*
PI_THREAD (logging_thread)
{
	while(substate.mode!=STOPPED){
		FILE *fd = fopen("log.txt", "a");
		char buffer[100] = {0};
		// add logging values to the next line
		sprintf(buffer, "%f %f %f %f %i %i %i %i %f %f %f %f\n",sstate.roll, sstate.pitch[0], sstate.yaw[0], sstate.depth[0],sstate.x[0],
		sstate.y[0], sstate.radius[0], setpoint.x - sstate.x[0], sstate.esc_out[0], sstate.esc_out[1], sstate.esc_out[2], sstate.esc_out[3]);
		fputs(buffer, fd);
		fclose(fd);
		//sleep for 100 ms

		usleep(100000);
	}
	return 0;
}
*/

/******************************************************************************
 * User Interface Thread
 * void* userInterface(void* arg)
 *
 * Interfaces with the user, asks for input
 *****************************************************************************/
 void* userInterface(void* arg)
 {
  // Declare local constant variables
  float _kp, _ki, _kd;

  // Wait a until everything is initialized before starting
  while(substate.mode == INITIALIZING)
  {
    // Waiting...
    auv_usleep(100000);
  }

  // Prompt user for values continuously until the program exits
  while(substate.mode != STOPPED)
  {
    // Prompt for kp
    std::cout << "Kp: ";
    std::cin >> _kp;

    // Prompt for ki
    std::cout << "Ki: ";
    std::cin >> _ki;

    // Prompt for kd
    std::cout << "Kd: ";
    std::cin >> _kd;

    // Give a newline
    std::cout << std::endl;

    // Reset gain values
    yaw_pid.kp = _kp;
    yaw_pid.ki = _ki;
    yaw_pid.kd = _kd;

    // Clear errors
    yaw_pid.perr = 0;
    yaw_pid.ierr = 0;
    yaw_pid.derr = 0;

    // Start RUNNING again
    substate.mode = RUNNING;

    // Restart timer!
	  start = time(0);

    // Aaaaaaand, WAIT!
    auv_usleep(12*1000000);
  }

  // Exit thread
  pthread_exit(NULL);
 }
<|endoftext|>