<commit_before>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2009 Emmanuel Benazera, juban@free.fr
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 **/

#include "search_snippet.h"
#include "miscutil.h"
#include "encode.h"

#include <iostream>

using sp::miscutil;
using sp::encode;

namespace seeks_plugins
{
   search_snippet::search_snippet()
     :_rank(0),_seeks_ir(0.0),_seeks_rank(0),_doc_type(WEBPAGE)
       {
       }

   search_snippet::search_snippet(const short &rank)
     :_rank(rank),_seeks_ir(0.0),_seeks_rank(0),_doc_type(WEBPAGE)
       {
       }

   search_snippet::~search_snippet()
     {
     }

   void search_snippet::highlight_query(std::vector<std::string> &words,
					std::string &str)
     {
	if (words.empty())
	  return;

	// sort words by size.
	std::sort(words.begin(),words.end(),std::greater<std::string>());

	// surround every of those words appearing within the
	// argument string with   for html
	// bold format. TODO: green ?
	for (size_t i=0;i<words.size();i++)
	  {
	     if (words.at(i).length() > 2)
	       {
		  std::string bold_str = "" + words.at(i) + "";
		  miscutil::ci_replace_in_string(str,words.at(i),bold_str);
	       }
	  }
     }

   std::ostream& search_snippet::print(std::ostream &output)
     {
	output << "-----------------------------------\n";
	output << "- seeks rank: " << _seeks_rank << std::endl;
	output << "- rank: " << _rank << std::endl;
	output << "- title: " << _title << std::endl;
	output << "- url: " << _url << std::endl;
	output << "- cite: " << _cite << std::endl;
	output << "- cached: " << _cached << std::endl;
	output << "- summary: " << _summary << std::endl;
	output << "- file format: " << _file_format << std::endl;
	output << "- date: " << _date << std::endl;
	output << "- lang: " << _lang << std::endl;
	if (_doc_type == FORUM)
	  output << "- forum thread info: " << _forum_thread_info << std::endl;
	output << "-----------------------------------\n";

	return output;
     }

   std::string search_snippet::to_html() const
     {
	std::vector<std::string> words;
	return to_html_with_highlight(words);
     }

   std::string search_snippet::to_html_with_highlight(std::vector<std::string> &words) const
     {
	static std::string se_icon = "";

	std::string html_content = "

";

	const char *title_enc = encode::html_encode(_title.c_str());
	html_content += title_enc;
	free_const(title_enc);
	html_content += "";

	if (_engine.to_ulong()&SE_GOOGLE)
	  {
	     std::string ggle_se_icon = se_icon;
	     miscutil::replace_in_string(ggle_se_icon,"icon","seeks_wb_google");
	     miscutil::replace_in_string(ggle_se_icon,"hspace=\"2\"","hspace=\"5\"");
	     html_content += ggle_se_icon;
	  }
	if (_engine.to_ulong()&SE_CUIL)
	  {
	     std::string cuil_se_icon = se_icon;
	     miscutil::replace_in_string(cuil_se_icon,"icon","seeks_wb_cuil");
	     html_content += cuil_se_icon;
	  }
	if (_engine.to_ulong()&SE_BING)
	  {
	     std::string bing_se_icon = se_icon;
	     miscutil::replace_in_string(bing_se_icon,"icon","seeks_wb_bing");
	     html_content += bing_se_icon;
	  }

	html_content += "
";

	if (_summary != "")
	  {
	     html_content += "
";
	     std::string summary = _summary;
	     search_snippet::highlight_query(words,summary);
	     html_content += summary;
	  }
	else html_content += "
";

	if (_cite != "")
	  {
	     const char *cite_enc = encode::html_encode(_cite.c_str());
	     html_content += "
";
	     html_content += cite_enc;
	     free_const(cite_enc);
	     html_content += "";
	  }

	if (!_cached.empty())
	  {
	      html_content += "Cached";
	  }
	else if (!_archive.empty())
	  {
	     html_content += _archive;
	     html_content += " \">Archive";
	  }

	html_content += "

\n";

	/* std::cout << "html_content:\n";
	 std::cout << html_content << std::endl; */

	return html_content;
     }

   void search_snippet::set_url(const std::string &url)
     {
	// decode url.
	char* str = encode::url_decode(url.c_str());
	_url = std::string(str);
	free(str);
     }

   void search_snippet::set_url(const char *url)
     {
	// decode url.
	char *str = encode::url_decode(url);
	_url = std::string(str);
	free(str);
     }

   void search_snippet::set_summary(const char *summary)
     {
	// encode html so tags are not interpreted.
	char* str = encode::html_encode(summary);
	_summary = std::string(str);
	free(str);
     }

   void search_snippet::set_summary(const std::string &summary)
     {

	// encode html so tags are not interpreted.
	char* str = encode::html_encode(summary.c_str());
	_summary = std::string(str);
	free(str);
     }

   void search_snippet::set_archive_link()
     {
	if (_cached.empty())
	  _archive = "http://web.archive.org/web/*/" + _url;
     }

   // static.
   void search_snippet::delete_snippets(std::vector<search_snippet*> &snippets)
     {
	size_t snippets_size = snippets.size();
	for (size_t i=0;i<snippets_size; i++)
	  delete snippets.at(i);
	snippets.clear();
     }

   void search_snippet::merge_snippets(search_snippet *s1,
				       const search_snippet *s2)
     {
	// seeks_rank is updated after merging.
	// search engine rank.
	s1->_rank = std::min(s1->_rank,s2->_rank);

	// search engine.
	s1->_engine |= s2->_engine;

	// cached link.
	if (s1->_cached.empty())
	  s1->_cached = s2->_cached;

	// summary.
	if (s1->_summary.length() < s2->_summary.length())
	  s1->_summary = s2->_summary;

	// file format.
	if (s1->_file_format.length() < s2->_file_format.length())  // we could do better here, ok enough for now.
	  s1->_file_format = s2->_file_format;
     }

} /* end of namespace. */
<commit_msg>fixed archive link rendering<commit_after>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2009 Emmanuel Benazera, juban@free.fr
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 **/

#include "search_snippet.h"
#include "miscutil.h"
#include "encode.h"

#include <iostream>

using sp::miscutil;
using sp::encode;

namespace seeks_plugins
{
   search_snippet::search_snippet()
     :_rank(0),_seeks_ir(0.0),_seeks_rank(0),_doc_type(WEBPAGE)
       {
       }

   search_snippet::search_snippet(const short &rank)
     :_rank(rank),_seeks_ir(0.0),_seeks_rank(0),_doc_type(WEBPAGE)
       {
       }

   search_snippet::~search_snippet()
     {
     }

   void search_snippet::highlight_query(std::vector<std::string> &words,
					std::string &str)
     {
	if (words.empty())
	  return;

	// sort words by size.
	std::sort(words.begin(),words.end(),std::greater<std::string>());

	// surround every of those words appearing within the
	// argument string with   for html
	// bold format. TODO: green ?
	for (size_t i=0;i<words.size();i++)
	  {
	     if (words.at(i).length() > 2)
	       {
		  std::string bold_str = "" + words.at(i) + "";
		  miscutil::ci_replace_in_string(str,words.at(i),bold_str);
	       }
	  }
     }

   std::ostream& search_snippet::print(std::ostream &output)
     {
	output << "-----------------------------------\n";
	output << "- seeks rank: " << _seeks_rank << std::endl;
	output << "- rank: " << _rank << std::endl;
	output << "- title: " << _title << std::endl;
	output << "- url: " << _url << std::endl;
	output << "- cite: " << _cite << std::endl;
	output << "- cached: " << _cached << std::endl;
	output << "- summary: " << _summary << std::endl;
	output << "- file format: " << _file_format << std::endl;
	output << "- date: " << _date << std::endl;
	output << "- lang: " << _lang << std::endl;
	if (_doc_type == FORUM)
	  output << "- forum thread info: " << _forum_thread_info << std::endl;
	output << "-----------------------------------\n";

	return output;
     }

   std::string search_snippet::to_html() const
     {
	std::vector<std::string> words;
	return to_html_with_highlight(words);
     }

   std::string search_snippet::to_html_with_highlight(std::vector<std::string> &words) const
     {
	static std::string se_icon = "";

	std::string html_content = "

";

	const char *title_enc = encode::html_encode(_title.c_str());
	html_content += title_enc;
	free_const(title_enc);
	html_content += "";

	if (_engine.to_ulong()&SE_GOOGLE)
	  {
	     std::string ggle_se_icon = se_icon;
	     miscutil::replace_in_string(ggle_se_icon,"icon","seeks_wb_google");
	     miscutil::replace_in_string(ggle_se_icon,"hspace=\"2\"","hspace=\"5\"");
	     html_content += ggle_se_icon;
	  }
	if (_engine.to_ulong()&SE_CUIL)
	  {
	     std::string cuil_se_icon = se_icon;
	     miscutil::replace_in_string(cuil_se_icon,"icon","seeks_wb_cuil");
	     html_content += cuil_se_icon;
	  }
	if (_engine.to_ulong()&SE_BING)
	  {
	     std::string bing_se_icon = se_icon;
	     miscutil::replace_in_string(bing_se_icon,"icon","seeks_wb_bing");
	     html_content += bing_se_icon;
	  }

	html_content += "
";

	if (_summary != "")
	  {
	     html_content += "
";
	     std::string summary = _summary;
	     search_snippet::highlight_query(words,summary);
	     html_content += summary;
	  }
	else html_content += "
";

	if (_cite != "")
	  {
	     const char *cite_enc = encode::html_encode(_cite.c_str());
	     html_content += "
";
	     html_content += cite_enc;
	     free_const(cite_enc);
	     html_content += "";
	  }

	if (!_cached.empty())
	  {
	     html_content += "Cached";
	  }
	else if (!_archive.empty())
	  {
	     html_content += "Archive";
	  }

	html_content += "

\n";

	/* std::cout << "html_content:\n";
	 std::cout << html_content << std::endl; */

	return html_content;
     }

   void search_snippet::set_url(const std::string &url)
     {
	// decode url.
	char* str = encode::url_decode(url.c_str());
	_url = std::string(str);
	free(str);
     }

   void search_snippet::set_url(const char *url)
     {
	// decode url.
	char *str = encode::url_decode(url);
	_url = std::string(str);
	free(str);
     }

   void search_snippet::set_summary(const char *summary)
     {
	// encode html so tags are not interpreted.
	char* str = encode::html_encode(summary);
	_summary = std::string(str);
	free(str);
     }

   void search_snippet::set_summary(const std::string &summary)
     {

	// encode html so tags are not interpreted.
	char* str = encode::html_encode(summary.c_str());
	_summary = std::string(str);
	free(str);
     }

   void search_snippet::set_archive_link()
     {
	if (_cached.empty())
	  _archive = "http://web.archive.org/web/*/" + _url;
     }

   // static.
   void search_snippet::delete_snippets(std::vector<search_snippet*> &snippets)
     {
	size_t snippets_size = snippets.size();
	for (size_t i=0;i<snippets_size; i++)
	  delete snippets.at(i);
	snippets.clear();
     }

   void search_snippet::merge_snippets(search_snippet *s1,
				       const search_snippet *s2)
     {
	// seeks_rank is updated after merging.
	// search engine rank.
	s1->_rank = std::min(s1->_rank,s2->_rank);

	// search engine.
	s1->_engine |= s2->_engine;

	// cached link.
	if (s1->_cached.empty())
	  s1->_cached = s2->_cached;

	// summary.
	if (s1->_summary.length() < s2->_summary.length())
	  s1->_summary = s2->_summary;

	// file format.
	if (s1->_file_format.length() < s2->_file_format.length())  // we could do better here, ok enough for now.
	  s1->_file_format = s2->_file_format;
     }

} /* end of namespace. */
<|endoftext|>


<commit_before>//===--- TerminalDisplayWin.h - Output To Windows Console -------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the interface for writing to a Windows console
//  i.e. cmd.exe.
//
//  Axel Naumann <axel@cern.ch>, 2011-05-12
//===----------------------------------------------------------------------===//

#ifdef _WIN32
#include "textinput/TerminalDisplayWin.h"
#include "textinput/Color.h"

#include <assert.h>

#ifdef UNICODE
#define filename L"CONOUT$"
#else
#define filename "CONOUT$"
#endif

namespace textinput {
  TerminalDisplayWin::TerminalDisplayWin():
    TerminalDisplay(false), fStartLine(0), fIsAttached(false),
    fDefaultAttributes(0), fOldCodePage(::GetConsoleOutputCP()) {
    DWORD mode;
    SetIsTTY(::GetConsoleMode(::GetStdHandle(STD_INPUT_HANDLE), &mode) != 0);

    fOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
    bool isConsole = ::GetConsoleMode(fOut, &fOldMode) != 0;
    if (!isConsole) {
      // Prevent redirection from stealing our console handle,
      // simply open our own.
      fOut = ::CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL, NULL);
      ::GetConsoleMode(fOut, &fOldMode);
    } else {
      // disable unicode (UTF-8) for the time being, since it causes
      // problems on Windows 10
      //::SetConsoleOutputCP(65001); // Force UTF-8 output
    }
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    ::GetConsoleScreenBufferInfo(fOut, &csbi);
    fDefaultAttributes = csbi.wAttributes;
    assert(fDefaultAttributes != 0 && "~TerminalDisplayWin broken");
    fMyMode = fOldMode | ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
    HandleResizeEvent();
  }

#undef filename

  TerminalDisplayWin::~TerminalDisplayWin() {
    if (fDefaultAttributes) {
      ::SetConsoleTextAttribute(fOut, fDefaultAttributes);
      // We allocated CONOUT$:
      CloseHandle(fOut);
    }
    ::SetConsoleOutputCP(fOldCodePage);
  }

  void
  TerminalDisplayWin::HandleResizeEvent() {
    if (IsTTY()) {
      CONSOLE_SCREEN_BUFFER_INFO Info;
      if (!::GetConsoleScreenBufferInfo(fOut, &Info)) {
        ShowError("resize / getting console info");
        return;
      }
      SetWidth(Info.dwSize.X);
    }
  }

  void
  TerminalDisplayWin::SetColor(char CIdx, const Color& C) {
    WORD Attribs = 0;
    // There is no underline since DOS has died.
    if (C.fModifiers & Color::kModUnderline) Attribs |= BACKGROUND_INTENSITY;
    if (C.fModifiers & Color::kModBold) Attribs |= FOREGROUND_INTENSITY;
    if (C.fR > 64) Attribs |= FOREGROUND_RED;
    if (C.fG > 64) Attribs |= FOREGROUND_GREEN;
    if (C.fB > 64) Attribs |= FOREGROUND_BLUE;
    // if CIdx is 0 (default) then use the original console text color
    // (instead of the greyish one)
    if (CIdx == 0)
      ::SetConsoleTextAttribute(fOut, fDefaultAttributes);
    else
      ::SetConsoleTextAttribute(fOut, Attribs);
  }

  void
  TerminalDisplayWin::CheckCursorPos() {
    if (!IsTTY()) return;
    // Did something print something on the screen?
    // I.e. did the cursor move?
    CONSOLE_SCREEN_BUFFER_INFO CSI;
    if (::GetConsoleScreenBufferInfo(fOut, &CSI)) {
      if (CSI.dwCursorPosition.X != fWritePos.fCol
        || CSI.dwCursorPosition.Y != fWritePos.fLine + fStartLine) {
        fStartLine = CSI.dwCursorPosition.Y;
        if (CSI.dwCursorPosition.X) {
          // fStartLine may be a couple of lines higher (or more precisely
          // the number of written lines higher)
          fStartLine -= fWritePos.fLine;
        }
        fWritePos.fCol = 0;
        fWritePos.fLine = 0;
      }
    }
  }

  void
  TerminalDisplayWin::Move(Pos P) {
    CheckCursorPos();
    MoveInternal(P);
    fWritePos = P;
  }

  void
  TerminalDisplayWin::MoveInternal(Pos P) {
    if (IsTTY()) {
      COORD C = {P.fCol, P.fLine + fStartLine};
      ::SetConsoleCursorPosition(fOut, C);
    }
  }

  void
  TerminalDisplayWin::MoveFront() {
    Pos P(fWritePos);
    P.fCol = 0;
    MoveInternal(P);
  }

  void
  TerminalDisplayWin::MoveUp(size_t nLines /* = 1 */) {
    Pos P(fWritePos);
    --P.fLine;
    MoveInternal(P);
  }

  void
  TerminalDisplayWin::MoveDown(size_t nLines /* = 1 */) {
    Pos P(fWritePos);
    ++P.fLine;
    MoveInternal(P);
  }

  void
  TerminalDisplayWin::MoveRight(size_t nCols /* = 1 */) {
    Pos P(fWritePos);
    ++P.fCol;
    MoveInternal(P);
  }

  void
  TerminalDisplayWin::MoveLeft(size_t nCols /* = 1 */) {
    Pos P(fWritePos);
    --P.fCol;
    MoveInternal(P);
  }

  void
  TerminalDisplayWin::EraseToRight() {
    DWORD NumWritten;
    COORD C = {fWritePos.fCol, fWritePos.fLine + fStartLine};
    ::FillConsoleOutputCharacter(fOut, ' ', GetWidth() - C.X, C,
      &NumWritten);
    // It wraps, so move up and reset WritePos:
    //MoveUp();
    //++WritePos.Line;
  }

  void
  TerminalDisplayWin::WriteRawString(const char *text, size_t len) {
    DWORD NumWritten = 0;
    if (IsTTY()) {
      WriteConsole(fOut, text, (DWORD) len, &NumWritten, NULL);
    } else {
      WriteFile(fOut, text, (DWORD) len, &NumWritten, NULL);
    }
    if (NumWritten != len) {
      ShowError("writing to output");
    }
  }

  void
  TerminalDisplayWin::Attach() {
    // set to noecho
    if (fIsAttached || !IsTTY()) return;
    if (!::SetConsoleMode(fOut, fMyMode)) {
      ShowError("attaching to console output");
    }
    CONSOLE_SCREEN_BUFFER_INFO Info;
    if (!::GetConsoleScreenBufferInfo(fOut, &Info)) {
      ShowError("attaching / getting console info");
    } else {
      fStartLine = Info.dwCursorPosition.Y;
      if (Info.dwCursorPosition.X) {
        // Whooa - where are we?! Newline and cross fingers:
        WriteRawString("\n", 1);
        ++fStartLine;
      }
    }
    fIsAttached = true;
  }

  void
  TerminalDisplayWin::Detach() {
    if (!fIsAttached || !IsTTY()) return;
    if (!SetConsoleMode(fOut, fOldMode)) {
      ShowError("detaching to console output");
    }
    TerminalDisplay::Detach();
    fIsAttached = false;
  }

  void
  TerminalDisplayWin::ShowError(const char* Where) const {
    DWORD Err = GetLastError();
    LPVOID MsgBuf = 0;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
      FORMAT_MESSAGE_IGNORE_INSERTS, NULL, Err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
      (LPTSTR) &MsgBuf, 0, NULL);

    printf("Error %d in textinput::TerminalDisplayWin %s: %s\n", Err, Where, MsgBuf);
    LocalFree(MsgBuf);
  }

}

#endif // ifdef _WIN32
<commit_msg>text input: fix windows warnings<commit_after>//===--- TerminalDisplayWin.h - Output To Windows Console -------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the interface for writing to a Windows console
//  i.e. cmd.exe.
//
//  Axel Naumann <axel@cern.ch>, 2011-05-12
//===----------------------------------------------------------------------===//

#ifdef _WIN32
#include "textinput/TerminalDisplayWin.h"
#include "textinput/Color.h"

#include <assert.h>

#ifdef UNICODE
#define filename L"CONOUT$"
#else
#define filename "CONOUT$"
#endif

namespace textinput {
  TerminalDisplayWin::TerminalDisplayWin():
    TerminalDisplay(false), fStartLine(0), fIsAttached(false),
    fDefaultAttributes(0), fOldCodePage(::GetConsoleOutputCP()) {
    DWORD mode;
    SetIsTTY(::GetConsoleMode(::GetStdHandle(STD_INPUT_HANDLE), &mode) != 0);

    fOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
    bool isConsole = ::GetConsoleMode(fOut, &fOldMode) != 0;
    if (!isConsole) {
      // Prevent redirection from stealing our console handle,
      // simply open our own.
      fOut = ::CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL, NULL);
      ::GetConsoleMode(fOut, &fOldMode);
    } else {
      // disable unicode (UTF-8) for the time being, since it causes
      // problems on Windows 10
      //::SetConsoleOutputCP(65001); // Force UTF-8 output
    }
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    ::GetConsoleScreenBufferInfo(fOut, &csbi);
    fDefaultAttributes = csbi.wAttributes;
    assert(fDefaultAttributes != 0 && "~TerminalDisplayWin broken");
    fMyMode = fOldMode | ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
    HandleResizeEvent();
  }

#undef filename

  TerminalDisplayWin::~TerminalDisplayWin() {
    if (fDefaultAttributes) {
      ::SetConsoleTextAttribute(fOut, fDefaultAttributes);
      // We allocated CONOUT$:
      CloseHandle(fOut);
    }
    ::SetConsoleOutputCP(fOldCodePage);
  }

  void
  TerminalDisplayWin::HandleResizeEvent() {
    if (IsTTY()) {
      CONSOLE_SCREEN_BUFFER_INFO Info;
      if (!::GetConsoleScreenBufferInfo(fOut, &Info)) {
        ShowError("resize / getting console info");
        return;
      }
      SetWidth(Info.dwSize.X);
    }
  }

  void
  TerminalDisplayWin::SetColor(char CIdx, const Color& C) {
    WORD Attribs = 0;
    // There is no underline since DOS has died.
    if (C.fModifiers & Color::kModUnderline) Attribs |= BACKGROUND_INTENSITY;
    if (C.fModifiers & Color::kModBold) Attribs |= FOREGROUND_INTENSITY;
    if (C.fR > 64) Attribs |= FOREGROUND_RED;
    if (C.fG > 64) Attribs |= FOREGROUND_GREEN;
    if (C.fB > 64) Attribs |= FOREGROUND_BLUE;
    // if CIdx is 0 (default) then use the original console text color
    // (instead of the greyish one)
    if (CIdx == 0)
      ::SetConsoleTextAttribute(fOut, fDefaultAttributes);
    else
      ::SetConsoleTextAttribute(fOut, Attribs);
  }

  void
  TerminalDisplayWin::CheckCursorPos() {
    if (!IsTTY()) return;
    // Did something print something on the screen?
    // I.e. did the cursor move?
    CONSOLE_SCREEN_BUFFER_INFO CSI;
    if (::GetConsoleScreenBufferInfo(fOut, &CSI)) {
      if (CSI.dwCursorPosition.X != fWritePos.fCol
        || CSI.dwCursorPosition.Y != fWritePos.fLine + fStartLine) {
        fStartLine = CSI.dwCursorPosition.Y;
        if (CSI.dwCursorPosition.X) {
          // fStartLine may be a couple of lines higher (or more precisely
          // the number of written lines higher)
          fStartLine -= fWritePos.fLine;
        }
        fWritePos.fCol = 0;
        fWritePos.fLine = 0;
      }
    }
  }

  void
  TerminalDisplayWin::Move(Pos P) {
    CheckCursorPos();
    MoveInternal(P);
    fWritePos = P;
  }

  void
  TerminalDisplayWin::MoveInternal(Pos P) {
    if (IsTTY()) {
      COORD C = { (SHORT) P.fCol, (SHORT) (P.fLine + fStartLine) };
      ::SetConsoleCursorPosition(fOut, C);
    }
  }

  void
  TerminalDisplayWin::MoveFront() {
    Pos P(fWritePos);
    P.fCol = 0;
    MoveInternal(P);
  }

  void
  TerminalDisplayWin::MoveUp(size_t nLines /* = 1 */) {
    Pos P(fWritePos);
    --P.fLine;
    MoveInternal(P);
  }

  void
  TerminalDisplayWin::MoveDown(size_t nLines /* = 1 */) {
    Pos P(fWritePos);
    ++P.fLine;
    MoveInternal(P);
  }

  void
  TerminalDisplayWin::MoveRight(size_t nCols /* = 1 */) {
    Pos P(fWritePos);
    ++P.fCol;
    MoveInternal(P);
  }

  void
  TerminalDisplayWin::MoveLeft(size_t nCols /* = 1 */) {
    Pos P(fWritePos);
    --P.fCol;
    MoveInternal(P);
  }

  void
  TerminalDisplayWin::EraseToRight() {
    DWORD NumWritten;
    COORD C = { (SHORT) fWritePos.fCol, (SHORT) (fWritePos.fLine + fStartLine) };
    ::FillConsoleOutputCharacter(fOut, ' ', GetWidth() - C.X, C,
      &NumWritten);
    // It wraps, so move up and reset WritePos:
    //MoveUp();
    //++WritePos.Line;
  }

  void
  TerminalDisplayWin::WriteRawString(const char *text, size_t len) {
    DWORD NumWritten = 0;
    if (IsTTY()) {
      WriteConsole(fOut, text, (DWORD) len, &NumWritten, NULL);
    } else {
      WriteFile(fOut, text, (DWORD) len, &NumWritten, NULL);
    }
    if (NumWritten != len) {
      ShowError("writing to output");
    }
  }

  void
  TerminalDisplayWin::Attach() {
    // set to noecho
    if (fIsAttached || !IsTTY()) return;
    if (!::SetConsoleMode(fOut, fMyMode)) {
      ShowError("attaching to console output");
    }
    CONSOLE_SCREEN_BUFFER_INFO Info;
    if (!::GetConsoleScreenBufferInfo(fOut, &Info)) {
      ShowError("attaching / getting console info");
    } else {
      fStartLine = Info.dwCursorPosition.Y;
      if (Info.dwCursorPosition.X) {
        // Whooa - where are we?! Newline and cross fingers:
        WriteRawString("\n", 1);
        ++fStartLine;
      }
    }
    fIsAttached = true;
  }

  void
  TerminalDisplayWin::Detach() {
    if (!fIsAttached || !IsTTY()) return;
    if (!SetConsoleMode(fOut, fOldMode)) {
      ShowError("detaching to console output");
    }
    TerminalDisplay::Detach();
    fIsAttached = false;
  }

  void
  TerminalDisplayWin::ShowError(const char* Where) const {
    DWORD Err = GetLastError();
    LPVOID MsgBuf = 0;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
      FORMAT_MESSAGE_IGNORE_INSERTS, NULL, Err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
      (LPTSTR) &MsgBuf, 0, NULL);

    printf("Error %d in textinput::TerminalDisplayWin %s: %s\n", Err, Where, (const char *) MsgBuf);
    LocalFree(MsgBuf);
  }

}

#endif // ifdef _WIN32
<|endoftext|>


<commit_before>//
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2013 Project Chrono
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file at the top level of the distribution
// and at http://projectchrono.org/license-chrono.txt.
//

//
//   Demo code (advanced), about
//
//     - loading an Abaqus tetahedrom mesh
//     - apply a load to the mesh using an external tool,
//       say CFD or SPH (here simulated as a function in this .cpp file)
//       that is perform a cosimulation.

#include "chrono/geometry/ChTriangleMeshConnected.h"
#include "chrono/solver/ChSolverMINRES.h"
#include "chrono/physics/ChLoadContainer.h"
#include "chrono/physics/ChSystem.h"
#include "chrono/physics/ChSystemDEM.h"

#include "chrono_irrlicht/ChIrrApp.h"
#include "chrono_vehicle/ChVehicleModelData.h"
#include "chrono_vehicle/terrain/DeformableTerrain.h"

using namespace chrono;
using namespace chrono::irrlicht;

using namespace irr;

int main(int argc, char* argv[]) {
    // Global parameter for tire:
    double tire_rad = 0.8;
    double tire_vel_z0 = -3;
    ChVector<> tire_center(0, 0.02+tire_rad, 0);

    double tire_w0 = tire_vel_z0/tire_rad;

    // Create a Chrono::Engine physical system
    ChSystemDEM my_system;

    // Create the Irrlicht visualization (open the Irrlicht device,
    // bind a simple user interface, etc. etc.)
    ChIrrApp application(&my_system, L"Deformable soil", core::dimension2d<u32>(1280, 720), false, true);

    // Easy shortcuts to add camera, lights, logo and sky in Irrlicht scene:
    application.AddTypicalLogo();
    application.AddTypicalSky();
    application.AddTypicalLights();
    application.AddTypicalCamera(core::vector3df(1.0f, 1.4f, -1.2f), core::vector3df(0, (f32)tire_rad, 0));
    application.AddLightWithShadow(core::vector3df(1.5f, 5.5f, -2.5f), core::vector3df(0, 0, 0), 3, 2.2, 7.2, 40, 512,
                                   video::SColorf(0.8f, 0.8f, 1.0f));

    std::shared_ptr<ChBody> mtruss (new ChBody);
    mtruss->SetBodyFixed(true);
    my_system.Add(mtruss);

    //
    // CREATE A RIGID BODY WITH A MESH
    //

    // Create also a rigid body with a rigid mesh that will be used for the cosimulation,
    // this time the ChLoadContactSurfaceMesh cannot be used as in the FEA case, so we
    // will use the ChLoadBodyMesh class:

    std::shared_ptr<ChBody> mrigidbody (new ChBody);
    my_system.Add(mrigidbody);
    mrigidbody->SetMass(200);
    mrigidbody->SetInertiaXX(ChVector<>(20,20,20));
    mrigidbody->SetPos(tire_center + ChVector<>(0,0.3,0));

    std::shared_ptr<ChTriangleMeshShape> mrigidmesh(new ChTriangleMeshShape);
    mrigidmesh->GetMesh().LoadWavefrontMesh(GetChronoDataFile("tractor_wheel.obj"));
    //mrigidmesh->GetMesh().Transform(VNULL, Q_from_AngAxis(CH_C_PI, VECT_Y) );
    mrigidbody->AddAsset(mrigidmesh);

    mrigidbody->GetCollisionModel()->ClearModel();
    mrigidbody->GetCollisionModel()->AddTriangleMesh(mrigidmesh->GetMesh(), false, false, VNULL,
                                                     ChMatrix33<>(1), 0.01);
    mrigidbody->GetCollisionModel()->BuildModel();
    mrigidbody->SetCollide(true);

    std::shared_ptr<ChColorAsset> mcol(new ChColorAsset);
    mcol->SetColor(ChColor(0.3f, 0.3f, 0.3f));
    mrigidbody->AddAsset(mcol);

    std::shared_ptr<ChLinkEngine> myengine(new ChLinkEngine);
    myengine->Set_shaft_mode(ChLinkEngine::ENG_SHAFT_OLDHAM);
    myengine->Set_eng_mode(ChLinkEngine::ENG_MODE_SPEED);
    if (auto mfun = std::dynamic_pointer_cast<ChFunction_Const>(myengine->Get_spe_funct()) )
        mfun->Set_yconst(CH_C_PI / 4.0);
    myengine->Initialize(mrigidbody, mtruss, ChCoordsys<>(tire_center, Q_from_AngAxis(CH_C_PI_2,VECT_Y)));
    my_system.Add(myengine);

    //
    // THE DEFORMABLE TERRAIN
    //

    // Create the 'deformable terrain' object
    vehicle::DeformableTerrain mterrain(&my_system);

    // Optionally, displace/tilt/rotate the terrain reference plane:
    mterrain.SetPlane(ChCoordsys<>(ChVector<>(0, 0, 0.5)));

    // Initialize the geometry of the soil: use either a regular grid:
     mterrain.Initialize(0.2,1.5,5,20,60);
    // or use a height map:
    //mterrain.Initialize(vehicle::GetDataFile("terrain/height_maps/test64.bmp"), "test64", 1.6, 1.6, 0, 0.3);

    // Set the soil terramechanical parameters:
    mterrain.SetSoilParametersSCM(1.2e6,  // Bekker Kphi
                                    0,   // Bekker Kc
                                    1.1, // Bekker n exponent
                                    0,   // Mohr cohesive limit (Pa)
                                    30,  // Mohr friction limit (degrees)
                                    0.01,// Janosi shear coefficient (m)
                                    5e7  // Elastic stiffness (Pa/m), before plastic yeld, must be > Kphi
                                    );
    mterrain.SetBulldozingFlow(true);    // inflate soil at the border of the rut
    mterrain.SetBulldozingParameters(55, // angle of friction for erosion of displaced material at the border of the rut
                                    0.8, // displaced material vs downward pressed material.
                                    2,   // number of erosion refinements per timestep
                                    10); // number of concentric vertex selections subject to erosion
    // Turn on the automatic level of detail refinement, so a coarse terrain mesh
    // is automatically improved by adding more points under the wheel contact patch:
    mterrain.SetAutomaticRefinement(true);
    mterrain.SetAutomaticRefinementResolution(0.04);

    // Set some visualization parameters: either with a texture, or with falsecolor plot, etc.
    //mterrain.SetTexture(vehicle::GetDataFile("terrain/textures/grass.jpg"), 16, 16);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_PRESSURE, 0, 30000.2);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_PRESSURE_YELD, 0, 30000.2);
    mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_SINKAGE, 0, 0.15);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_SINKAGE_PLASTIC, 0, 0.15);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_SINKAGE_ELASTIC, 0, 0.05);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_STEP_PLASTIC_FLOW, 0, 0.0001);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_ISLAND_ID, 0, 8);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_IS_TOUCHED, 0, 8);
    mterrain.GetMesh()->SetWireframe(false);

    // ==IMPORTANT!== Use this function for adding a ChIrrNodeAsset to all items
    application.AssetBindAll();

    // ==IMPORTANT!== Use this function for 'converting' into Irrlicht meshes the assets
    application.AssetUpdateAll();

    // Use shadows in realtime view
    application.AddShadowAll();

    // ==IMPORTANT!== Mark completion of system construction
    my_system.SetupInitial();

    //
    // THE SOFT-REAL-TIME CYCLE
    //

 /*
        // Change solver to embedded MINRES
        // NOTE! it is strongly advised that you compile the optional MKL module
        // if you need higher precision, and switch to its MKL solver - see demos for FEA & MKL.
    my_system.SetSolverType(ChSystem::SOLVER_MINRES);
    my_system.SetSolverWarmStarting(true);  // this helps a lot to speedup convergence in this class of problems
    my_system.SetMaxItersSolverSpeed(40);
    my_system.SetTolForce(1e-10);
  */

    application.SetTimestep(0.005);

    while (application.GetDevice()->run()) {
        application.BeginScene();

        application.DrawAll();

        application.DoStep();

        ChIrrTools::drawColorbar(0,30000, "Pressure yeld [Pa]", application.GetDevice(),  1180);

        application.EndScene();
    }

    return 0;
}
<commit_msg>Just formatting and comments.<commit_after>//
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2013 Project Chrono
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file at the top level of the distribution
// and at http://projectchrono.org/license-chrono.txt.
//

//
//   Demo code (advanced), about
//
//     - using the SCM semi-empirical model for deformable soil

#include "chrono/geometry/ChTriangleMeshConnected.h"
#include "chrono/solver/ChSolverMINRES.h"
#include "chrono/physics/ChLoadContainer.h"
#include "chrono/physics/ChSystem.h"
#include "chrono/physics/ChSystemDEM.h"

#include "chrono_irrlicht/ChIrrApp.h"
#include "chrono_vehicle/ChVehicleModelData.h"
#include "chrono_vehicle/terrain/DeformableTerrain.h"

using namespace chrono;
using namespace chrono::irrlicht;

using namespace irr;

int main(int argc, char* argv[]) {
    // Global parameter for tire:
    double tire_rad = 0.8;
    double tire_vel_z0 = -3;
    ChVector<> tire_center(0, 0.02+tire_rad, 0);

    double tire_w0 = tire_vel_z0/tire_rad;

    // Create a Chrono::Engine physical system
    ChSystemDEM my_system;

    // Create the Irrlicht visualization (open the Irrlicht device,
    // bind a simple user interface, etc. etc.)
    ChIrrApp application(&my_system, L"Deformable soil", core::dimension2d<u32>(1280, 720), false, true);

    // Easy shortcuts to add camera, lights, logo and sky in Irrlicht scene:
    application.AddTypicalLogo();
    application.AddTypicalSky();
    application.AddTypicalLights();
    application.AddTypicalCamera(core::vector3df(1.0f, 1.4f, -1.2f), core::vector3df(0, (f32)tire_rad, 0));
    application.AddLightWithShadow(core::vector3df(1.5f, 5.5f, -2.5f), core::vector3df(0, 0, 0), 3, 2.2, 7.2, 40, 512,
                                   video::SColorf(0.8f, 0.8f, 1.0f));

    std::shared_ptr<ChBody> mtruss (new ChBody);
    mtruss->SetBodyFixed(true);
    my_system.Add(mtruss);

    //
    // CREATE A RIGID BODY WITH A MESH
    //

    // Create also a rigid body with a rigid mesh that will be used for the cosimulation,
    // this time the ChLoadContactSurfaceMesh cannot be used as in the FEA case, so we
    // will use the ChLoadBodyMesh class:

    std::shared_ptr<ChBody> mrigidbody (new ChBody);
    my_system.Add(mrigidbody);
    mrigidbody->SetMass(200);
    mrigidbody->SetInertiaXX(ChVector<>(20,20,20));
    mrigidbody->SetPos(tire_center + ChVector<>(0,0.3,0));

    std::shared_ptr<ChTriangleMeshShape> mrigidmesh(new ChTriangleMeshShape);
    mrigidmesh->GetMesh().LoadWavefrontMesh(GetChronoDataFile("tractor_wheel.obj"));
    mrigidbody->AddAsset(mrigidmesh);

    mrigidbody->GetCollisionModel()->ClearModel();
    mrigidbody->GetCollisionModel()->AddTriangleMesh(mrigidmesh->GetMesh(), false, false, VNULL,
                                                     ChMatrix33<>(1), 0.01);
    mrigidbody->GetCollisionModel()->BuildModel();
    mrigidbody->SetCollide(true);

    std::shared_ptr<ChColorAsset> mcol(new ChColorAsset);
    mcol->SetColor(ChColor(0.3f, 0.3f, 0.3f));
    mrigidbody->AddAsset(mcol);

    std::shared_ptr<ChLinkEngine> myengine(new ChLinkEngine);
    myengine->Set_shaft_mode(ChLinkEngine::ENG_SHAFT_OLDHAM);
    myengine->Set_eng_mode(ChLinkEngine::ENG_MODE_SPEED);
    if (auto mfun = std::dynamic_pointer_cast<ChFunction_Const>(myengine->Get_spe_funct()) )
        mfun->Set_yconst(CH_C_PI / 4.0);
    myengine->Initialize(mrigidbody, mtruss, ChCoordsys<>(tire_center, Q_from_AngAxis(CH_C_PI_2,VECT_Y)));
    my_system.Add(myengine);

    //
    // THE DEFORMABLE TERRAIN
    //

    // Create the 'deformable terrain' object
    vehicle::DeformableTerrain mterrain(&my_system);

    // Optionally, displace/tilt/rotate the terrain reference plane:
    mterrain.SetPlane(ChCoordsys<>(ChVector<>(0, 0, 0.5)));

    // Initialize the geometry of the soil: use either a regular grid:
     mterrain.Initialize(0.2,1.5,5,20,60);
    // or use a height map:
    //mterrain.Initialize(vehicle::GetDataFile("terrain/height_maps/test64.bmp"), "test64", 1.6, 1.6, 0, 0.3);

    // Set the soil terramechanical parameters:
    mterrain.SetSoilParametersSCM(1.2e6,  // Bekker Kphi
                                    0,   // Bekker Kc
                                    1.1, // Bekker n exponent
                                    0,   // Mohr cohesive limit (Pa)
                                    30,  // Mohr friction limit (degrees)
                                    0.01,// Janosi shear coefficient (m)
                                    5e7  // Elastic stiffness (Pa/m), before plastic yeld, must be > Kphi
                                    );
    mterrain.SetBulldozingFlow(true);    // inflate soil at the border of the rut
    mterrain.SetBulldozingParameters(55, // angle of friction for erosion of displaced material at the border of the rut
                                    0.8, // displaced material vs downward pressed material.
                                    5,   // number of erosion refinements per timestep
                                    10); // number of concentric vertex selections subject to erosion
    // Turn on the automatic level of detail refinement, so a coarse terrain mesh
    // is automatically improved by adding more points under the wheel contact patch:
    mterrain.SetAutomaticRefinement(true);
    mterrain.SetAutomaticRefinementResolution(0.04);

    // Set some visualization parameters: either with a texture, or with falsecolor plot, etc.
    //mterrain.SetTexture(vehicle::GetDataFile("terrain/textures/grass.jpg"), 16, 16);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_PRESSURE, 0, 30000.2);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_PRESSURE_YELD, 0, 30000.2);
    mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_SINKAGE, 0, 0.15);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_SINKAGE_PLASTIC, 0, 0.15);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_SINKAGE_ELASTIC, 0, 0.05);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_STEP_PLASTIC_FLOW, 0, 0.0001);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_ISLAND_ID, 0, 8);
    //mterrain.SetPlotType(vehicle::DeformableTerrain::PLOT_IS_TOUCHED, 0, 8);
    mterrain.GetMesh()->SetWireframe(true);

    // ==IMPORTANT!== Use this function for adding a ChIrrNodeAsset to all items
    application.AssetBindAll();

    // ==IMPORTANT!== Use this function for 'converting' into Irrlicht meshes the assets
    application.AssetUpdateAll();

    // Use shadows in realtime view
    application.AddShadowAll();

    // ==IMPORTANT!== Mark completion of system construction
    my_system.SetupInitial();

    //
    // THE SOFT-REAL-TIME CYCLE
    //

    application.SetTimestep(0.005);

    while (application.GetDevice()->run()) {
        application.BeginScene();

        application.DrawAll();

        application.DoStep();

        ChIrrTools::drawColorbar(0,30000, "Pressure yeld [Pa]", application.GetDevice(),  1180);

        application.EndScene();
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "TrackingWorker.hpp"

#include <boost/chrono/duration.hpp>
#include <ros/console.h>
#include <opencv2/core/core.hpp>
#include <map>

#include "../../matlab/profiling.hpp"

TrackingWorker::TrackingWorker(IPositionReceiver *receiver) : errorGraph(200, "Difference")
{
	assert(receiver != 0);

	this->receiver = receiver;
	stop = false;

	std::map<int, cv::Scalar> colors;
	colors[0] = cv::Scalar(0, 255, 0);
	colors[1] = cv::Scalar(0, 255, 255);
	colors[2] = cv::Scalar(255, 0, 255);
	errorGraph.setColors(colors);

	thread = new boost::thread(boost::bind(&TrackingWorker::run, this));
}

TrackingWorker::~TrackingWorker()
{
	stop = true;
	thread->join();
}

void TrackingWorker::run()
{
	ROS_INFO("Started tracking thread");

	bool receivedFirstPosition = false;
	int emptyCount = 0;

	while (!stop) {
		std::vector<CameraData> data = dequeue();

		if (data.size() > 0) {
			emptyCount = 0;

			if (!receivedFirstPosition) {
				receivedFirstPosition = true;
				ROS_INFO("Found quadcopter %d", data[0].quadcopterId);
			}

			// ROS_DEBUG("Got info from camera %d: [%.2f, %.2f, %.2f]", data[0].camNo, data[0].cameraVector.getV1(), data[0].cameraVector.getV2(), data[0].cameraVector.getV3());

			Vector position = tracker.updatePosition(data);

			for (size_t i = 0; i < data.size(); i++) {
				errorGraph.nextPoint(tracker.getDistance(), data[i].camNo);
			}

			std::vector<Vector> positions;
			std::vector<int> ids;
			std::vector<int> updates;
			positions.push_back(position);
			ids.push_back(data[0].quadcopterId);
			updates.push_back(1);

			if (position.isValid()) {
				receiver->updatePositions(positions, ids, updates);
			}
		} else if (receivedFirstPosition) {
			emptyCount++;

			if (emptyCount == 5) {
				ROS_WARN("Position update buffer is empty!");
				emptyCount = 0;
			}

			// Produce a context switch, since there are no good results anyways and to prevent busy waiting
			usleep(0);
		}
	}

	ROS_INFO("Stopped tracking thread");
}

void TrackingWorker::updatePosition(Vector cameraVector, int camNo, int quadcopterId, long int time)
{
	CameraData data;
	data.cameraVector = cameraVector;
	data.camNo = camNo;
	data.quadcopterId = quadcopterId;
	data.valid = true;
	data.time = time;

	updatePosition(data);
}

void TrackingWorker::updatePosition(CameraData data)
{
	enqueue(data);
}

void TrackingWorker::enqueue(CameraData data)
{
	boost::mutex::scoped_lock lock(queueMutex);

	queue.enqueue(data);

	queueEmpty.notify_one();
}

std::vector<CameraData> TrackingWorker::dequeue()
{
	boost::mutex::scoped_lock lock(queueMutex);

	if (!dataAvailable()) {
		queueEmpty.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(100));
	}

	if (dataAvailable()) {
		return queue.dequeue();
	} else {
		return std::vector<CameraData>();
	}
}

bool TrackingWorker::dataAvailable()
{
	return queue.dataAvailable();
}

bool TrackingWorker::calibrate(ChessboardData *chessboard, int camNo)
{
	return tracker.calibrate(chessboard, camNo);
}

Vector TrackingWorker::getCameraPosition(int camNo)
{
	return tracker.getPosition(camNo);
}

cv::Mat TrackingWorker::getIntrinsicsMatrix(int camNo)
{
	return tracker.getIntrinsicsMatrix(camNo);
}

cv::Mat TrackingWorker::getDistortionCoefficients(int camNo)
{
	return tracker.getDistortionCoefficients(camNo);
}

void TrackingWorker::updateTrackingArea()
{
	receiver->setTrackingArea(tracker.getTrackingArea());
}<commit_msg>Prevent burst dequeueing when queue can not give data<commit_after>#include "TrackingWorker.hpp"

#include <boost/chrono/duration.hpp>
#include <ros/console.h>
#include <opencv2/core/core.hpp>
#include <map>

#include "../../matlab/profiling.hpp"

TrackingWorker::TrackingWorker(IPositionReceiver *receiver) : errorGraph(200, "Difference")
{
	assert(receiver != 0);

	this->receiver = receiver;
	stop = false;

	std::map<int, cv::Scalar> colors;
	colors[0] = cv::Scalar(0, 255, 0);
	colors[1] = cv::Scalar(0, 255, 255);
	colors[2] = cv::Scalar(255, 0, 255);
	errorGraph.setColors(colors);

	thread = new boost::thread(boost::bind(&TrackingWorker::run, this));
}

TrackingWorker::~TrackingWorker()
{
	stop = true;
	thread->join();
}

void TrackingWorker::run()
{
	ROS_INFO("Started tracking thread");

	bool receivedFirstPosition = false;
	int emptyCount = 0;

	while (!stop) {
		std::vector<CameraData> data = dequeue();

		if (data.size() > 0) {
			emptyCount = 0;

			if (!receivedFirstPosition) {
				receivedFirstPosition = true;
				ROS_INFO("Found quadcopter %d", data[0].quadcopterId);
			}

			// ROS_DEBUG("Got info from camera %d: [%.2f, %.2f, %.2f]", data[0].camNo, data[0].cameraVector.getV1(), data[0].cameraVector.getV2(), data[0].cameraVector.getV3());

			Vector position = tracker.updatePosition(data);

			for (size_t i = 0; i < data.size(); i++) {
				errorGraph.nextPoint(tracker.getDistance(), data[i].camNo);
			}

			std::vector<Vector> positions;
			std::vector<int> ids;
			std::vector<int> updates;
			positions.push_back(position);
			ids.push_back(data[0].quadcopterId);
			updates.push_back(1);

			if (position.isValid()) {
				receiver->updatePositions(positions, ids, updates);
			}
		} else if (receivedFirstPosition) {
			emptyCount++;

			if (emptyCount == 5) {
				ROS_WARN("Position update buffer is empty!");
				emptyCount = 0;
			}

			boost::mutex::scoped_lock lock(queueMutex);
			queueEmpty.wait(lock);
		}
	}

	ROS_INFO("Stopped tracking thread");
}

void TrackingWorker::updatePosition(Vector cameraVector, int camNo, int quadcopterId, long int time)
{
	CameraData data;
	data.cameraVector = cameraVector;
	data.camNo = camNo;
	data.quadcopterId = quadcopterId;
	data.valid = true;
	data.time = time;

	updatePosition(data);
}

void TrackingWorker::updatePosition(CameraData data)
{
	enqueue(data);
}

void TrackingWorker::enqueue(CameraData data)
{
	boost::mutex::scoped_lock lock(queueMutex);

	queue.enqueue(data);

	queueEmpty.notify_all();
}

std::vector<CameraData> TrackingWorker::dequeue()
{
	boost::mutex::scoped_lock lock(queueMutex);

	if (!dataAvailable()) {
		queueEmpty.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(100));
	}

	if (dataAvailable()) {
		return queue.dequeue();
	} else {
		return std::vector<CameraData>();
	}
}

bool TrackingWorker::dataAvailable()
{
	return queue.dataAvailable();
}

bool TrackingWorker::calibrate(ChessboardData *chessboard, int camNo)
{
	return tracker.calibrate(chessboard, camNo);
}

Vector TrackingWorker::getCameraPosition(int camNo)
{
	return tracker.getPosition(camNo);
}

cv::Mat TrackingWorker::getIntrinsicsMatrix(int camNo)
{
	return tracker.getIntrinsicsMatrix(camNo);
}

cv::Mat TrackingWorker::getDistortionCoefficients(int camNo)
{
	return tracker.getDistortionCoefficients(camNo);
}

void TrackingWorker::updateTrackingArea()
{
	receiver->setTrackingArea(tracker.getTrackingArea());
}<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Networks and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef JUBATUS_SERVER_FRAMEWORK_SERVER_HELPER_HPP_
#define JUBATUS_SERVER_FRAMEWORK_SERVER_HELPER_HPP_

#include <sys/types.h>
#include <unistd.h>

#include <map>
#include <string>
#include "jubatus/util/lang/bind.h"
#include "jubatus/util/lang/shared_ptr.h"
#include "jubatus/util/system/sysstat.h"
#include "jubatus/util/system/time_util.h"

#include "jubatus/core/common/jsonconfig.hpp"
#include "mixer/mixer.hpp"
#include "server_util.hpp"
#include "../../config.hpp"
#include "../common/lock_service.hpp"
#include "../common/mprpc/rpc_server.hpp"
#include "../common/signals.hpp"
#include "../common/config.hpp"
#include "../common/logger/logger.hpp"

using jubatus::util::system::time::clock_time;
using jubatus::util::system::time::get_clock_time;

namespace jubatus {
namespace server {
namespace framework {

class server_helper_impl {
 public:
  explicit server_helper_impl(const server_argv& a);
  ~server_helper_impl();

  void prepare_for_start(const server_argv& a, bool use_cht);
  void prepare_for_run(const server_argv& a, bool use_cht);
  void get_config_lock(const server_argv& a, int retry);
  void prepare_for_stop(const server_argv& a);

  jubatus::util::lang::shared_ptr<common::lock_service> zk() const {
    return zk_;
  }

 private:
  jubatus::util::lang::shared_ptr<common::lock_service> zk_;
  jubatus::util::lang::shared_ptr<common::try_lockable> zk_config_lock_;
};

template<typename Server>
class server_helper {
 public:
  typedef typename Server::status_t status_t;

  explicit server_helper(const server_argv& a, bool use_cht = false)
      : impl_(a),
        start_time_(get_clock_time()),
        use_cht_(use_cht) {
    impl_.prepare_for_start(a, use_cht);
    server_.reset(new Server(a, impl_.zk()));

    impl_.get_config_lock(a, 3);

    try {
      if (a.is_standalone() && !a.modelpath.empty()) {
        // Load from a specified model file.
        // `load_file` implies `set_config`; no further actions needed.
        if (!a.configpath.empty()) {
          LOG(INFO) << "both model file and configuration are specified; "
                    << "using configuration from model file";
        }
        server_->load_file(a.modelpath);
      } else {
        server_->set_config(get_conf(a));
      }
    } catch (const core::common::jsonconfig::cast_check_error& e) {
      core::common::config_exception config_error;
      const core::common::jsonconfig::config_error_list& errors = e.errors();
      for (core::common::jsonconfig::config_error_list::const_iterator
          it = errors.begin(), end = errors.end(); it != end; ++it) {
        config_error << core::common::exception::error_message((*it)->what());
      }
      // send error message to caller
      throw JUBATUS_EXCEPTION(config_error);
    } catch (const jubatus::util::lang::parse_error& e) {
      // exit immediately on JSON parse error with exit-code 1
      std::string msg =
          std::string("syntax error in configuration: ") +
          (a.is_standalone() ?
           a.configpath :
           std::string("<zookeeper>")) + ":" +
          jubatus::util::lang::lexical_cast<std::string>(e.lineno()) + ":" +
          jubatus::util::lang::lexical_cast<std::string>(e.pos()) + " " +
          e.msg();

      LOG(ERROR) << msg;
      exit(1);
    } catch (const std::runtime_error& e) {
      throw;
    }
 }

  std::map<std::string, std::string> get_loads() const {
    std::map<std::string, std::string> result;
    {
      jubatus::util::system::sysstat::sysstat_ret sys;
      get_sysstat(sys);
      result["loadavg"] =
          jubatus::util::lang::lexical_cast<std::string>(sys.loadavg);
      result["total_memory"] = jubatus::util::lang::lexical_cast<std::string>(
          sys.total_memory);
      result["free_memory"] = jubatus::util::lang::lexical_cast<std::string>(
          sys.free_memory);
    }
    return result;
  }

  std::map<std::string, status_t> get_status() const {
    std::map<std::string, status_t> status;
    const server_argv& a = server_->argv();
    status_t& data = status[get_server_identifier(a)];

    const clock_time ct = get_clock_time();
    data["clock_time"] =
       jubatus::util::lang::lexical_cast<std::string>(ct.sec);
    data["start_time"] =
       jubatus::util::lang::lexical_cast<std::string>(start_time_.sec);
    data["uptime"] =
       jubatus::util::lang::lexical_cast<std::string>((ct - start_time_).sec);

    common::machine_status_t mt;
    common::get_machine_status(mt);
    data["VIRT"] =
        jubatus::util::lang::lexical_cast<std::string>(mt.vm_size);
    data["RSS"] =
        jubatus::util::lang::lexical_cast<std::string>(mt.vm_resident);
    data["SHR"] =
        jubatus::util::lang::lexical_cast<std::string>(mt.vm_share);

    data["timeout"] = jubatus::util::lang::lexical_cast<std::string>(a.timeout);
    data["threadnum"] =
        jubatus::util::lang::lexical_cast<std::string>(a.threadnum);
    data["datadir"] = a.datadir;
    data["is_standalone"] = jubatus::util::lang::lexical_cast<std::string>(
        a.is_standalone());
    data["VERSION"] = JUBATUS_VERSION;
    data["PROGNAME"] = a.program_name;
    data["type"] = a.type;
    data["logdir"] = a.logdir;
    data["log_config"] = a.log_config;

    std::string configpath;
    if (a.is_standalone()) {
      configpath = a.configpath;
    } else {
#ifdef HAVE_ZOOKEEPER_H
      // return zookeeper node name
      jubatus::server::common::build_config_path(configpath, a.type, a.name);
#endif
    }
    data["configpath"] = configpath;

    data["pid"] =
        jubatus::util::lang::lexical_cast<std::string>(getpid());
    data["user"] = jubatus::server::common::get_user_name();

    data["update_count"] = jubatus::util::lang::lexical_cast<std::string>(
        server_->update_count());

    data["last_saved"] =
        jubatus::util::lang::lexical_cast<std::string>
        (server_->last_saved_sec());
    data["last_saved_path"] = server_->last_saved_path();
    data["last_loaded"] =
        jubatus::util::lang::lexical_cast<std::string>
        (server_->last_loaded_sec());
    data["last_loaded_path"] = server_->last_loaded_path();

    server_->get_status(data);

    // distributed mode only
    if (!a.is_standalone()) {
      data["zk"] = a.z;
      data["name"] = a.name;
      data["interval_sec"] =
          jubatus::util::lang::lexical_cast<std::string>(a.interval_sec);
      data["interval_count"] = jubatus::util::lang::lexical_cast<std::string>(
          a.interval_count);
      data["zookeeper_timeout"] =
          jubatus::util::lang::lexical_cast<std::string>(a.zookeeper_timeout);
      data["interconnect_timeout"] =
          jubatus::util::lang::lexical_cast<std::string>
          (a.interconnect_timeout);
      data["connected_zookeeper"] = impl_.zk()->get_connected_host_and_port();
      data["use_cht"] = jubatus::util::lang::lexical_cast<std::string>(
          use_cht_);

      data["mixer"] = a.mixer;
      server_->get_mixer()->get_status(data);
    }

    return status;
  }

  int start(common::mprpc::rpc_server& serv) {
    const server_argv& a = server_->argv();

    try {
      serv.listen(a.port, a.bind_address);
      LOG(INFO) << "start listening at port " << a.port;

      start_time_ = get_clock_time();
      serv.start(a.threadnum, true);

      // RPC server started, then register group membership
      impl_.prepare_for_run(a, use_cht_);
      LOG(INFO) << common::get_program_name() << " RPC server startup";

      // Stop RPC server when terminate signal is sent
      common::set_action_on_term(
          jubatus::util::lang::bind(
              &server_helper::stop, this, jubatus::util::lang::ref(serv)));

      if (!a.is_standalone()) {
        // Start mixer and register active membership
        server_->get_mixer()->start();
      }

      // wait for termination
      serv.join();

      return 0;
    } catch (const mp::system_error& e) {
      if (e.code == EADDRINUSE) {
        LOG(FATAL) << "server failed to start: any process using port "
            << a.port << "?";
      } else {
        LOG(FATAL) << "server failed to start: " << e.what();
      }
    } catch (jubatus::core::common::exception::jubatus_exception&) {
      throw;
    } catch (const std::exception& e) {
      LOG(FATAL) << "server failed to start: " << e.what();
    }
    return -1;
  }

  void stop(common::mprpc::rpc_server& serv) {
    // stop mixer before RPC server stopped for avoiding mixer RPC call to the
    // server itself
    if (!server_->argv().is_standalone()) {
      LOG(INFO) << "stopping mixer thread";
      server_->get_mixer()->stop();
      impl_.prepare_for_stop(server_->argv());
    }

    LOG(INFO) << "stopping RPC server";
    serv.end();
  }

  jubatus::util::lang::shared_ptr<Server> server() const {
    return server_;
  }

  jubatus::util::concurrent::rw_mutex& rw_mutex() {
    return server_->rw_mutex();
  }

 private:
  jubatus::util::lang::shared_ptr<Server> server_;
  server_helper_impl impl_;
  clock_time start_time_;
  const bool use_cht_;
};

}  // namespace framework
}  // namespace server
}  // namespace jubatus

#define JRLOCK_(p) \
  ::jubatus::util::concurrent::scoped_rlock lk((p)->rw_mutex())

#define JWLOCK_(p) \
  ::jubatus::util::concurrent::scoped_wlock lk((p)->rw_mutex()); \
  (p)->server()->event_model_updated()

#define NOLOCK_(p)

#endif  // JUBATUS_SERVER_FRAMEWORK_SERVER_HELPER_HPP_
<commit_msg>fix code style<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Networks and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef JUBATUS_SERVER_FRAMEWORK_SERVER_HELPER_HPP_
#define JUBATUS_SERVER_FRAMEWORK_SERVER_HELPER_HPP_

#include <sys/types.h>
#include <unistd.h>

#include <map>
#include <string>
#include "jubatus/util/lang/bind.h"
#include "jubatus/util/lang/shared_ptr.h"
#include "jubatus/util/system/sysstat.h"
#include "jubatus/util/system/time_util.h"

#include "jubatus/core/common/jsonconfig.hpp"
#include "mixer/mixer.hpp"
#include "server_util.hpp"
#include "../../config.hpp"
#include "../common/lock_service.hpp"
#include "../common/mprpc/rpc_server.hpp"
#include "../common/signals.hpp"
#include "../common/config.hpp"
#include "../common/logger/logger.hpp"

using jubatus::util::system::time::clock_time;
using jubatus::util::system::time::get_clock_time;

namespace jubatus {
namespace server {
namespace framework {

class server_helper_impl {
 public:
  explicit server_helper_impl(const server_argv& a);
  ~server_helper_impl();

  void prepare_for_start(const server_argv& a, bool use_cht);
  void prepare_for_run(const server_argv& a, bool use_cht);
  void get_config_lock(const server_argv& a, int retry);
  void prepare_for_stop(const server_argv& a);

  jubatus::util::lang::shared_ptr<common::lock_service> zk() const {
    return zk_;
  }

 private:
  jubatus::util::lang::shared_ptr<common::lock_service> zk_;
  jubatus::util::lang::shared_ptr<common::try_lockable> zk_config_lock_;
};

template<typename Server>
class server_helper {
 public:
  typedef typename Server::status_t status_t;

  explicit server_helper(const server_argv& a, bool use_cht = false)
      : impl_(a),
        start_time_(get_clock_time()),
        use_cht_(use_cht) {
    impl_.prepare_for_start(a, use_cht);
    server_.reset(new Server(a, impl_.zk()));

    impl_.get_config_lock(a, 3);

    try {
      if (a.is_standalone() && !a.modelpath.empty()) {
        // Load from a specified model file.
        // `load_file` implies `set_config`; no further actions needed.
        if (!a.configpath.empty()) {
          LOG(INFO) << "both model file and configuration are specified; "
                    << "using configuration from model file";
        }
        server_->load_file(a.modelpath);
      } else {
        server_->set_config(get_conf(a));
      }
    } catch (const core::common::jsonconfig::cast_check_error& e) {
      core::common::config_exception config_error;
      const core::common::jsonconfig::config_error_list& errors = e.errors();
      for (core::common::jsonconfig::config_error_list::const_iterator
          it = errors.begin(), end = errors.end(); it != end; ++it) {
        config_error << core::common::exception::error_message((*it)->what());
      }
      // send error message to caller
      throw JUBATUS_EXCEPTION(config_error);
    } catch (const jubatus::util::lang::parse_error& e) {
      // exit immediately on JSON parse error with exit-code 1
      std::string msg =
          std::string("syntax error in configuration: ") +
          (a.is_standalone() ?
           a.configpath :
           std::string("<zookeeper>")) + ":" +
          jubatus::util::lang::lexical_cast<std::string>(e.lineno()) + ":" +
          jubatus::util::lang::lexical_cast<std::string>(e.pos()) + " " +
          e.msg();

      LOG(ERROR) << msg;
      exit(1);
    } catch (const std::runtime_error& e) {
      throw;
    }
  }

  std::map<std::string, std::string> get_loads() const {
    std::map<std::string, std::string> result;
    {
      jubatus::util::system::sysstat::sysstat_ret sys;
      get_sysstat(sys);
      result["loadavg"] =
          jubatus::util::lang::lexical_cast<std::string>(sys.loadavg);
      result["total_memory"] = jubatus::util::lang::lexical_cast<std::string>(
          sys.total_memory);
      result["free_memory"] = jubatus::util::lang::lexical_cast<std::string>(
          sys.free_memory);
    }
    return result;
  }

  std::map<std::string, status_t> get_status() const {
    std::map<std::string, status_t> status;
    const server_argv& a = server_->argv();
    status_t& data = status[get_server_identifier(a)];

    const clock_time ct = get_clock_time();
    data["clock_time"] =
       jubatus::util::lang::lexical_cast<std::string>(ct.sec);
    data["start_time"] =
       jubatus::util::lang::lexical_cast<std::string>(start_time_.sec);
    data["uptime"] =
       jubatus::util::lang::lexical_cast<std::string>((ct - start_time_).sec);

    common::machine_status_t mt;
    common::get_machine_status(mt);
    data["VIRT"] =
        jubatus::util::lang::lexical_cast<std::string>(mt.vm_size);
    data["RSS"] =
        jubatus::util::lang::lexical_cast<std::string>(mt.vm_resident);
    data["SHR"] =
        jubatus::util::lang::lexical_cast<std::string>(mt.vm_share);

    data["timeout"] = jubatus::util::lang::lexical_cast<std::string>(a.timeout);
    data["threadnum"] =
        jubatus::util::lang::lexical_cast<std::string>(a.threadnum);
    data["datadir"] = a.datadir;
    data["is_standalone"] = jubatus::util::lang::lexical_cast<std::string>(
        a.is_standalone());
    data["VERSION"] = JUBATUS_VERSION;
    data["PROGNAME"] = a.program_name;
    data["type"] = a.type;
    data["logdir"] = a.logdir;
    data["log_config"] = a.log_config;

    std::string configpath;
    if (a.is_standalone()) {
      configpath = a.configpath;
    } else {
#ifdef HAVE_ZOOKEEPER_H
      // return zookeeper node name
      jubatus::server::common::build_config_path(configpath, a.type, a.name);
#endif
    }
    data["configpath"] = configpath;

    data["pid"] =
        jubatus::util::lang::lexical_cast<std::string>(getpid());
    data["user"] = jubatus::server::common::get_user_name();

    data["update_count"] = jubatus::util::lang::lexical_cast<std::string>(
        server_->update_count());

    data["last_saved"] =
        jubatus::util::lang::lexical_cast<std::string>
        (server_->last_saved_sec());
    data["last_saved_path"] = server_->last_saved_path();
    data["last_loaded"] =
        jubatus::util::lang::lexical_cast<std::string>
        (server_->last_loaded_sec());
    data["last_loaded_path"] = server_->last_loaded_path();

    server_->get_status(data);

    // distributed mode only
    if (!a.is_standalone()) {
      data["zk"] = a.z;
      data["name"] = a.name;
      data["interval_sec"] =
          jubatus::util::lang::lexical_cast<std::string>(a.interval_sec);
      data["interval_count"] = jubatus::util::lang::lexical_cast<std::string>(
          a.interval_count);
      data["zookeeper_timeout"] =
          jubatus::util::lang::lexical_cast<std::string>(a.zookeeper_timeout);
      data["interconnect_timeout"] =
          jubatus::util::lang::lexical_cast<std::string>
          (a.interconnect_timeout);
      data["connected_zookeeper"] = impl_.zk()->get_connected_host_and_port();
      data["use_cht"] = jubatus::util::lang::lexical_cast<std::string>(
          use_cht_);

      data["mixer"] = a.mixer;
      server_->get_mixer()->get_status(data);
    }

    return status;
  }

  int start(common::mprpc::rpc_server& serv) {
    const server_argv& a = server_->argv();

    try {
      serv.listen(a.port, a.bind_address);
      LOG(INFO) << "start listening at port " << a.port;

      start_time_ = get_clock_time();
      serv.start(a.threadnum, true);

      // RPC server started, then register group membership
      impl_.prepare_for_run(a, use_cht_);
      LOG(INFO) << common::get_program_name() << " RPC server startup";

      // Stop RPC server when terminate signal is sent
      common::set_action_on_term(
          jubatus::util::lang::bind(
              &server_helper::stop, this, jubatus::util::lang::ref(serv)));

      if (!a.is_standalone()) {
        // Start mixer and register active membership
        server_->get_mixer()->start();
      }

      // wait for termination
      serv.join();

      return 0;
    } catch (const mp::system_error& e) {
      if (e.code == EADDRINUSE) {
        LOG(FATAL) << "server failed to start: any process using port "
            << a.port << "?";
      } else {
        LOG(FATAL) << "server failed to start: " << e.what();
      }
    } catch (jubatus::core::common::exception::jubatus_exception&) {
      throw;
    } catch (const std::exception& e) {
      LOG(FATAL) << "server failed to start: " << e.what();
    }
    return -1;
  }

  void stop(common::mprpc::rpc_server& serv) {
    // stop mixer before RPC server stopped for avoiding mixer RPC call to the
    // server itself
    if (!server_->argv().is_standalone()) {
      LOG(INFO) << "stopping mixer thread";
      server_->get_mixer()->stop();
      impl_.prepare_for_stop(server_->argv());
    }

    LOG(INFO) << "stopping RPC server";
    serv.end();
  }

  jubatus::util::lang::shared_ptr<Server> server() const {
    return server_;
  }

  jubatus::util::concurrent::rw_mutex& rw_mutex() {
    return server_->rw_mutex();
  }

 private:
  jubatus::util::lang::shared_ptr<Server> server_;
  server_helper_impl impl_;
  clock_time start_time_;
  const bool use_cht_;
};

}  // namespace framework
}  // namespace server
}  // namespace jubatus

#define JRLOCK_(p) \
  ::jubatus::util::concurrent::scoped_rlock lk((p)->rw_mutex())

#define JWLOCK_(p) \
  ::jubatus::util::concurrent::scoped_wlock lk((p)->rw_mutex()); \
  (p)->server()->event_model_updated()

#define NOLOCK_(p)

#endif  // JUBATUS_SERVER_FRAMEWORK_SERVER_HELPER_HPP_
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2011-2016 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/network/settings.hpp>

#include <bitcoin/bitcoin.hpp>

namespace libbitcoin {
namespace network {

using namespace bc::asio;
using namespace bc::message;

// Common default values (no settings context).
settings::settings()
  : threads(50),
    protocol(version::level::maximum),
    inbound_connections(32),
    outbound_connections(4),
    manual_attempt_limit(0),
    connect_batch_size(5),
    connect_timeout_seconds(5),
    channel_handshake_seconds(30),
    channel_heartbeat_minutes(5),
    channel_inactivity_minutes(10),
    channel_expiration_minutes(1440),
    channel_germination_seconds(30),
    host_pool_capacity(1000),
    relay_transactions(true),
    hosts_file("hosts.cache"),
    debug_file("debug.log"),
    error_file("error.log"),
    self(unspecified_network_address)
{
}

// Use push_back due to initializer_list bug:
// stackoverflow.com/a/20168627/1172329
settings::settings(bc::settings context)
  : settings()
{
    // Handle deviations from common defaults.
    switch (context)
    {
        case bc::settings::mainnet:
        {
            identifier = 0x4d53564d;
            inbound_port = 5251;

            // Seeds based on bitcoinstats.com/network/dns-servers
            seeds.reserve(6);
            seeds.push_back({ "main-asia.metaverse.live", 5251 });
            seeds.push_back({ "main-americas.metaverse.live", 5251 });
            seeds.push_back({ "main-europe.metaverse.live", 5251 });
            seeds.push_back({ "main-asia.mvs.live", 5251 });
            seeds.push_back({ "main-americas.mvs.live", 5251 });
            seeds.push_back({ "main-europe.mvs.live", 5251 });
            break;
        }

        case bc::settings::testnet:
        {
            identifier = 0x73766d74;
            inbound_port = 15251;

            seeds.reserve(6);
            seeds.push_back({ "test-asia.metaverse.live", 15251 });
            seeds.push_back({ "test-americas.metaverse.live", 15251 });
            seeds.push_back({ "test-europe.metaverse.live", 15251 });
            seeds.push_back({ "test-asia.mvs.live", 15251 });
            seeds.push_back({ "test-americas.mvs.live", 15251 });
            seeds.push_back({ "test-europe.mvs.live", 15251 });
            break;
        }

        default:
        case bc::settings::none:
        {
        }
    }
}

duration settings::connect_timeout() const
{
    return seconds(connect_timeout_seconds);
}

duration settings::channel_handshake() const
{
    return seconds(channel_handshake_seconds);
}

duration settings::channel_heartbeat() const
{
    return minutes(channel_heartbeat_minutes);
}

duration settings::channel_inactivity() const
{
    return minutes(channel_inactivity_minutes);
}

duration settings::channel_expiration() const
{
    return minutes(channel_expiration_minutes);
}

duration settings::channel_germination() const
{
    return seconds(channel_germination_seconds);
}

} // namespace network
} // namespace libbitcoin
<commit_msg>change outbound connections as 8 for sync bug<commit_after>/**
 * Copyright (c) 2011-2016 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/network/settings.hpp>

#include <bitcoin/bitcoin.hpp>

namespace libbitcoin {
namespace network {

using namespace bc::asio;
using namespace bc::message;

// Common default values (no settings context).
settings::settings()
  : threads(50),
    protocol(version::level::maximum),
    inbound_connections(32),
    outbound_connections(8),
    manual_attempt_limit(0),
    connect_batch_size(5),
    connect_timeout_seconds(5),
    channel_handshake_seconds(30),
    channel_heartbeat_minutes(5),
    channel_inactivity_minutes(10),
    channel_expiration_minutes(1440),
    channel_germination_seconds(30),
    host_pool_capacity(1000),
    relay_transactions(true),
    hosts_file("hosts.cache"),
    debug_file("debug.log"),
    error_file("error.log"),
    self(unspecified_network_address)
{
}

// Use push_back due to initializer_list bug:
// stackoverflow.com/a/20168627/1172329
settings::settings(bc::settings context)
  : settings()
{
    // Handle deviations from common defaults.
    switch (context)
    {
        case bc::settings::mainnet:
        {
            identifier = 0x4d53564d;
            inbound_port = 5251;

            // Seeds based on bitcoinstats.com/network/dns-servers
            seeds.reserve(6);
            seeds.push_back({ "main-asia.metaverse.live", 5251 });
            seeds.push_back({ "main-americas.metaverse.live", 5251 });
            seeds.push_back({ "main-europe.metaverse.live", 5251 });
            seeds.push_back({ "main-asia.mvs.live", 5251 });
            seeds.push_back({ "main-americas.mvs.live", 5251 });
            seeds.push_back({ "main-europe.mvs.live", 5251 });
            break;
        }

        case bc::settings::testnet:
        {
            identifier = 0x73766d74;
            inbound_port = 15251;

            seeds.reserve(6);
            seeds.push_back({ "test-asia.metaverse.live", 15251 });
            seeds.push_back({ "test-americas.metaverse.live", 15251 });
            seeds.push_back({ "test-europe.metaverse.live", 15251 });
            seeds.push_back({ "test-asia.mvs.live", 15251 });
            seeds.push_back({ "test-americas.mvs.live", 15251 });
            seeds.push_back({ "test-europe.mvs.live", 15251 });
            break;
        }

        default:
        case bc::settings::none:
        {
        }
    }
}

duration settings::connect_timeout() const
{
    return seconds(connect_timeout_seconds);
}

duration settings::channel_handshake() const
{
    return seconds(channel_handshake_seconds);
}

duration settings::channel_heartbeat() const
{
    return minutes(channel_heartbeat_minutes);
}

duration settings::channel_inactivity() const
{
    return minutes(channel_inactivity_minutes);
}

duration settings::channel_expiration() const
{
    return minutes(channel_expiration_minutes);
}

duration settings::channel_germination() const
{
    return seconds(channel_germination_seconds);
}

} // namespace network
} // namespace libbitcoin
<|endoftext|>


<commit_before>/*
 * This file is part of Peli - universal JSON interaction library
 * Copyright (C) 2014  Alexey Chernov <4ernov@gmail.com>
 *
 * Peli is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <sstream>
#include <iostream>
#include <cmath>
#include <limits>

#include "peli/json/value.h"

#include "exception_check.h"

using namespace std;

using namespace peli;
using namespace peli::test;

int check_zero()
{
	const string str1 = "   [\n\t0   ]\r\n  ";
	const wstring str2 = L"[  \r\t0   ]\n\t  \n  \n\r  ";

	istringstream is1(str1);
	json::value v1;
	is1 >> v1;

	wistringstream is2(str2);
	json::wvalue v2;
	is2 >> v2;

	const json::array& arr1(get<json::array>(v1));
	const json::warray& arr2(get<json::warray>(v2));
	json::array ch1 { json::number(0) };
	json::warray ch2 { json::number(0) };

	if (arr1 != ch1)
		return -1;

	if (arr2 != ch2)
		return -2;

	return 0;
}

int check_integer()
{
	const string str1 = "   [\n\t-123456, 123456   ]\r\n  ";
	const wstring str2 = L"[  \r\t-123456, 123456   ]\n\t  \n  \n\r  ";

	istringstream is1(str1);
	json::value v1;
	is1 >> v1;

	wistringstream is2(str2);
	json::wvalue v2;
	is2 >> v2;

	const json::array& arr1(get<json::array>(v1));
	const json::warray& arr2(get<json::warray>(v2));
	json::array ch1 { json::number { -123456 }, json::number { 123456 } };
	json::warray ch2 { json::number { -123456 }, json::number { 123456 } };

	if (arr1 != ch1)
		return -3;

	if (arr2 != ch2)
		return -4;

	return 0;
}

int check_decimal_fraction()
{
	const string str1 = "   [\n\t3.4375, -3.4375, 0.04, -0.04   ]\r\n  ";
	const wstring str2 = L"[  \r\t3.4375, -3.4375, 0.04, -0.04   ]\n\t  \n  \n\r  ";

	istringstream is1(str1);
	json::value v1;
	is1 >> v1;

	wistringstream is2(str2);
	json::wvalue v2;
	is2 >> v2;

	const json::array& arr1(get<json::array>(v1));
	const json::warray& arr2(get<json::warray>(v2));
	json::array ch1
	{
		json::number(3.4375),
		json::number(-3.4375),
		json::value(json::number(0.04)),
		json::value(json::number(-0.04))
	};

	json::warray ch2
	{
		json::number(3.4375),
		json::number(-3.4375),
		json::wvalue(json::number(0.04)),
		json::wvalue(json::number(-0.04))
	};

	json::number precision = pow(10, -1 * (numeric_limits<json::number>::digits10 - 2));

	if (abs(get<json::number>(arr1[2]) - get<json::number>(ch1[2])) < precision)
		ch1[2] = arr1[2];

	if (abs(get<json::number>(arr1[3]) - get<json::number>(ch1[3])) < precision)
		ch1[3] = arr1[3];

	if (arr1 != ch1)
		return -5;

	if (arr2 != ch2)
		return -6;

	return 0;
}

int check_engineer_fraction()
{
	const string str1 = "   [\n\t0.34375e1, -0.34375e+1, 0.34375E1, -0.34375E+1, 4e-2, -4e-2   ]\r\n  ";
	const wstring str2 = L"[  \r\t0.34375e1, -0.34375e+1, 0.34375E1, -0.34375E+1, 4e-2, -4e-2   ]\n\t  \n  \n\r  ";

	istringstream is1(str1);
	json::value v1;
	is1 >> v1;

	wistringstream is2(str2);
	json::wvalue v2;
	is2 >> v2;

	const json::array& arr1(get<json::array>(v1));
	const json::warray& arr2(get<json::warray>(v2));
	json::array ch1
	{
		json::number { 3.4375 },
		json::number { -3.4375 },
		json::number { 3.4375 },
		json::number { -3.4375 },
		json::value(json::number(4e-2)),
		json::value(json::number(-4e-2))
	};

	json::warray ch2
	{
		json::number { 3.4375 },
		json::number { -3.4375 },
		json::number { 3.4375 },
		json::number { -3.4375 },
		json::wvalue(json::number(4e-2)),
		json::wvalue(json::number(-4e-2))
	};

	json::number precision = pow(10, -1 * (numeric_limits<json::number>::digits10 - 2));

	if (fabs(get<json::number>(arr1[4]) - get<json::number>(ch1[4])) < precision)
		ch1[4] = arr1[4];

	if (fabs(get<json::number>(arr1[5]) - get<json::number>(ch1[5])) < precision)
		ch1[5] = arr1[5];

	if (arr1 != ch1)
		return -7;

	if (arr2 != ch2)
		return -8;

	return 0;
}

int check_overflow()
{
	if (!has_thrown_on<invalid_argument>("[45e+1459823]"))
		return -9;

	return 0;
}

int main(int, char**)
{
	const int zr = check_zero();

	if (zr)
		return zr;

	const int ir = check_integer();

	if (ir)
		return ir;

	const int dr = check_decimal_fraction();

	if (dr)
		return dr;

	const int er = check_engineer_fraction();

	return er;
}
<commit_msg>Positive return codes and better handling for numbers as well<commit_after>/*
 * This file is part of Peli - universal JSON interaction library
 * Copyright (C) 2014  Alexey Chernov <4ernov@gmail.com>
 *
 * Peli is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <sstream>
#include <iostream>
#include <cmath>
#include <limits>

#include "peli/json/value.h"

#include "exception_check.h"

using namespace std;

using namespace peli;
using namespace peli::test;

int check_zero()
{
	const string str1 = "   [\n\t0   ]\r\n  ";
	const wstring str2 = L"[  \r\t0   ]\n\t  \n  \n\r  ";

	istringstream is1(str1);
	json::value v1;
	is1 >> v1;

	wistringstream is2(str2);
	json::wvalue v2;
	is2 >> v2;

	const json::array& arr1(get<json::array>(v1));
	const json::warray& arr2(get<json::warray>(v2));
	json::array ch1 { json::number(0) };
	json::warray ch2 { json::number(0) };

	if (arr1 != ch1)
		return 1;

	if (arr2 != ch2)
		return 2;

	return 0;
}

int check_integer()
{
	const string str1 = "   [\n\t-123456, 123456   ]\r\n  ";
	const wstring str2 = L"[  \r\t-123456, 123456   ]\n\t  \n  \n\r  ";

	istringstream is1(str1);
	json::value v1;
	is1 >> v1;

	wistringstream is2(str2);
	json::wvalue v2;
	is2 >> v2;

	const json::array& arr1(get<json::array>(v1));
	const json::warray& arr2(get<json::warray>(v2));
	json::array ch1 { json::number { -123456 }, json::number { 123456 } };
	json::warray ch2 { json::number { -123456 }, json::number { 123456 } };

	if (arr1 != ch1)
		return 3;

	if (arr2 != ch2)
		return 4;

	return 0;
}

int check_decimal_fraction()
{
	const string str1 = "   [\n\t3.4375, -3.4375, 0.04, -0.04   ]\r\n  ";
	const wstring str2 = L"[  \r\t3.4375, -3.4375, 0.04, -0.04   ]\n\t  \n  \n\r  ";

	istringstream is1(str1);
	json::value v1;
	is1 >> v1;

	wistringstream is2(str2);
	json::wvalue v2;
	is2 >> v2;

	const json::array& arr1(get<json::array>(v1));
	const json::warray& arr2(get<json::warray>(v2));
	json::array ch1
	{
		json::number(3.4375),
		json::number(-3.4375),
		json::value(json::number(0.04)),
		json::value(json::number(-0.04))
	};

	json::warray ch2
	{
		json::number(3.4375),
		json::number(-3.4375),
		json::wvalue(json::number(0.04)),
		json::wvalue(json::number(-0.04))
	};

	json::number precision = pow(10, -1 * (numeric_limits<json::number>::digits10 - 2));

	if (abs(get<json::number>(arr1[2]) - get<json::number>(ch1[2])) < precision)
		ch1[2] = arr1[2];

	if (abs(get<json::number>(arr1[3]) - get<json::number>(ch1[3])) < precision)
		ch1[3] = arr1[3];

	if (arr1 != ch1)
		return 5;

	if (arr2 != ch2)
		return 6;

	return 0;
}

int check_engineer_fraction()
{
	const string str1 = "   [\n\t0.34375e1, -0.34375e+1, 0.34375E1, -0.34375E+1, 4e-2, -4e-2   ]\r\n  ";
	const wstring str2 = L"[  \r\t0.34375e1, -0.34375e+1, 0.34375E1, -0.34375E+1, 4e-2, -4e-2   ]\n\t  \n  \n\r  ";

	istringstream is1(str1);
	json::value v1;
	is1 >> v1;

	wistringstream is2(str2);
	json::wvalue v2;
	is2 >> v2;

	const json::array& arr1(get<json::array>(v1));
	const json::warray& arr2(get<json::warray>(v2));
	json::array ch1
	{
		json::number { 3.4375 },
		json::number { -3.4375 },
		json::number { 3.4375 },
		json::number { -3.4375 },
		json::value(json::number(4e-2)),
		json::value(json::number(-4e-2))
	};

	json::warray ch2
	{
		json::number { 3.4375 },
		json::number { -3.4375 },
		json::number { 3.4375 },
		json::number { -3.4375 },
		json::wvalue(json::number(4e-2)),
		json::wvalue(json::number(-4e-2))
	};

	json::number precision = pow(10, -1 * (numeric_limits<json::number>::digits10 - 2));

	if (fabs(get<json::number>(arr1[4]) - get<json::number>(ch1[4])) < precision)
		ch1[4] = arr1[4];

	if (fabs(get<json::number>(arr1[5]) - get<json::number>(ch1[5])) < precision)
		ch1[5] = arr1[5];

	if (arr1 != ch1)
		return 7;

	if (arr2 != ch2)
		return 8;

	return 0;
}

int check_overflow()
{
	if (!has_thrown_on<invalid_argument>("[45e+1459823]"))
		return 9;

	return 0;
}

int main(int, char**)
{
	if (const auto r = check_zero())
		return r;

	if (const auto r = check_integer())
		return r;

	if (const auto r = check_decimal_fraction())
		return r;

	if (const auto r = check_engineer_fraction())
		return r;

	if (const auto r = check_overflow())
		return r;

	return 0;
}
<|endoftext|>