<commit_before>// Copyright (c) 2012 Intel Corp
// Copyright (c) 2012 The Chromium Authors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell co
// pies of the Software, and to permit persons to whom the Software is furnished
//  to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in al
// l copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IM
// PLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNES
// S FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
//  OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH
// ETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "content/nw/src/shell_main_delegate.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/utf_string_conversions.h"
#include "content/public/browser/browser_main_runner.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/nw/src/common/shell_switches.h"
#include "content/nw/src/nw_version.h"
#include "content/nw/src/renderer/shell_content_renderer_client.h"
#include "content/nw/src/shell_browser_main.h"
#include "content/nw/src/shell_content_browser_client.h"
#include "third_party/node/src/node_version.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"

#include <stdio.h>

#if defined(OS_MACOSX)
#include "content/shell/paths_mac.h"
#endif  // OS_MACOSX

#if defined(OS_WIN)
#include "base/logging_win.h"
#include <initguid.h>
#endif

namespace {

#if defined(OS_WIN)
// If "Content Shell" doesn't show up in your list of trace providers in
// Sawbuck, add these registry entries to your machine (NOTE the optional
// Wow6432Node key for x64 machines):
// 1. Find:  HKLM\SOFTWARE\[Wow6432Node\]Google\Sawbuck\Providers
// 2. Add a subkey with the name "{6A3E50A4-7E15-4099-8413-EC94D8C2A4B6}"
// 3. Add these values:
//    "default_flags"=dword:00000001
//    "default_level"=dword:00000004
//    @="Content Shell"

// {6A3E50A4-7E15-4099-8413-EC94D8C2A4B6}
const GUID kContentShellProviderName = {
    0x6a3e50a4, 0x7e15, 0x4099,
        { 0x84, 0x13, 0xec, 0x94, 0xd8, 0xc2, 0xa4, 0xb6 } };
#endif

void InitLogging() {
  logging::InitLogging(
#if defined(OS_WIN)
      L"debug.log",
#else
      "debug.log",
#endif
      logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
      logging::LOCK_LOG_FILE,
      logging::DELETE_OLD_LOG_FILE,
      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
  logging::SetLogItems(true, false, true, false);
}

}  // namespace

namespace content {

ShellMainDelegate::ShellMainDelegate() {
}

ShellMainDelegate::~ShellMainDelegate() {
}

bool ShellMainDelegate::BasicStartupComplete(int* exit_code) {
#if defined(OS_WIN)
  // Enable trace control and transport through event tracing for Windows.
  logging::LogEventProvider::Initialize(kContentShellProviderName);
#endif

  InitLogging();

  SetContentClient(&content_client_);
  return false;
}

void ShellMainDelegate::PreSandboxStartup() {
#if defined(OS_MACOSX)
  OverrideFrameworkBundlePath();
  OverrideChildProcessPath();
#endif  // OS_MACOSX
  InitializeResourceBundle();

  CommandLine* command_line = CommandLine::ForCurrentProcess();

  // Just prevent sandbox.
  command_line->AppendSwitch(switches::kNoSandbox);

  // Make sure we keep using only one render process for one app, by using the
  // process-per-tab mode, we can make Chrome only create new site instance
  // when we require to, the default mode is creating different site instances
  // for different domains.
  // This is needed because we want our Window API to have full control of new
  // windows created, which require all windows to be in one render process
  // host.
  command_line->AppendSwitch(switches::kProcessPerTab);
}

int ShellMainDelegate::RunProcess(
    const std::string& process_type,
    const MainFunctionParams& main_function_params) {
  if (!process_type.empty())
    return -1;

  return ShellBrowserMain(main_function_params);
}

void ShellMainDelegate::InitializeResourceBundle() {
  FilePath pak_file;
#if defined(OS_MACOSX)
  pak_file = GetResourcesPakFilePath();
#else
  FilePath pak_dir;
  PathService::Get(base::DIR_MODULE, &pak_dir);
  pak_file = pak_dir.Append(FILE_PATH_LITERAL("nw.pak"));
#endif
  ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
}

ContentBrowserClient* ShellMainDelegate::CreateContentBrowserClient() {
  browser_client_.reset(new ShellContentBrowserClient);
  return browser_client_.get();
}

ContentRendererClient* ShellMainDelegate::CreateContentRendererClient() {
  renderer_client_.reset(new ShellContentRendererClient);
  return renderer_client_.get();
}

}  // namespace content
<commit_msg>Allow file:// URIs can read other file:// URIs by default.   Fix #266.<commit_after>// Copyright (c) 2012 Intel Corp
// Copyright (c) 2012 The Chromium Authors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell co
// pies of the Software, and to permit persons to whom the Software is furnished
//  to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in al
// l copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IM
// PLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNES
// S FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
//  OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH
// ETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "content/nw/src/shell_main_delegate.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/utf_string_conversions.h"
#include "content/public/browser/browser_main_runner.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/nw/src/common/shell_switches.h"
#include "content/nw/src/nw_version.h"
#include "content/nw/src/renderer/shell_content_renderer_client.h"
#include "content/nw/src/shell_browser_main.h"
#include "content/nw/src/shell_content_browser_client.h"
#include "third_party/node/src/node_version.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"

#include <stdio.h>

#if defined(OS_MACOSX)
#include "content/shell/paths_mac.h"
#endif  // OS_MACOSX

#if defined(OS_WIN)
#include "base/logging_win.h"
#include <initguid.h>
#endif

namespace {

#if defined(OS_WIN)
// If "Content Shell" doesn't show up in your list of trace providers in
// Sawbuck, add these registry entries to your machine (NOTE the optional
// Wow6432Node key for x64 machines):
// 1. Find:  HKLM\SOFTWARE\[Wow6432Node\]Google\Sawbuck\Providers
// 2. Add a subkey with the name "{6A3E50A4-7E15-4099-8413-EC94D8C2A4B6}"
// 3. Add these values:
//    "default_flags"=dword:00000001
//    "default_level"=dword:00000004
//    @="Content Shell"

// {6A3E50A4-7E15-4099-8413-EC94D8C2A4B6}
const GUID kContentShellProviderName = {
    0x6a3e50a4, 0x7e15, 0x4099,
        { 0x84, 0x13, 0xec, 0x94, 0xd8, 0xc2, 0xa4, 0xb6 } };
#endif

void InitLogging() {
  logging::InitLogging(
#if defined(OS_WIN)
      L"debug.log",
#else
      "debug.log",
#endif
      logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
      logging::LOCK_LOG_FILE,
      logging::DELETE_OLD_LOG_FILE,
      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
  logging::SetLogItems(true, false, true, false);
}

}  // namespace

namespace content {

ShellMainDelegate::ShellMainDelegate() {
}

ShellMainDelegate::~ShellMainDelegate() {
}

bool ShellMainDelegate::BasicStartupComplete(int* exit_code) {
#if defined(OS_WIN)
  // Enable trace control and transport through event tracing for Windows.
  logging::LogEventProvider::Initialize(kContentShellProviderName);
#endif

  InitLogging();

  SetContentClient(&content_client_);
  return false;
}

void ShellMainDelegate::PreSandboxStartup() {
#if defined(OS_MACOSX)
  OverrideFrameworkBundlePath();
  OverrideChildProcessPath();
#endif  // OS_MACOSX
  InitializeResourceBundle();

  CommandLine* command_line = CommandLine::ForCurrentProcess();

  // Just prevent sandbox.
  command_line->AppendSwitch(switches::kNoSandbox);

  // Make sure we keep using only one render process for one app, by using the
  // process-per-tab mode, we can make Chrome only create new site instance
  // when we require to, the default mode is creating different site instances
  // for different domains.
  // This is needed because we want our Window API to have full control of new
  // windows created, which require all windows to be in one render process
  // host.
  command_line->AppendSwitch(switches::kProcessPerTab);

  // Allow file:// URIs can read other file:// URIs by default.
  command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
}

int ShellMainDelegate::RunProcess(
    const std::string& process_type,
    const MainFunctionParams& main_function_params) {
  if (!process_type.empty())
    return -1;

  return ShellBrowserMain(main_function_params);
}

void ShellMainDelegate::InitializeResourceBundle() {
  FilePath pak_file;
#if defined(OS_MACOSX)
  pak_file = GetResourcesPakFilePath();
#else
  FilePath pak_dir;
  PathService::Get(base::DIR_MODULE, &pak_dir);
  pak_file = pak_dir.Append(FILE_PATH_LITERAL("nw.pak"));
#endif
  ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
}

ContentBrowserClient* ShellMainDelegate::CreateContentBrowserClient() {
  browser_client_.reset(new ShellContentBrowserClient);
  return browser_client_.get();
}

ContentRendererClient* ShellMainDelegate::CreateContentRendererClient() {
  renderer_client_.reset(new ShellContentRendererClient);
  return renderer_client_.get();
}

}  // namespace content
<|endoftext|>


<commit_before>#include <iostream>

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <getopt.h>

#include "codes/uncoded.h"
#include "simulation/simulation.h"

[[noreturn]] static void usage() {
  std::cout << "--l <num>        "
            << "  "
            << "Choose code length l" << std::endl;
  std::cout << "--seed <num>     "
            << "  "
            << "Set seed of the random number generator." << std::endl;
  exit(-1);
}

int main(int argc, char *const argv[]) {
  unsigned long l = 0;
  uint64_t seed = 0;

  while (1) {
    static struct option options[] = {
      { "l", required_argument, nullptr, 'l' },
      { "seed", required_argument, nullptr, 's' },
      { nullptr, 0, nullptr, 0 },
    };

    int option_index = 0;
    int c = getopt_long_only(argc, argv, "", options, &option_index);
    if (c == -1)
      break;

    switch (c) {
    case 'l':
      l = strtoul(optarg, nullptr, 0);
      break;
    case 's':
      seed = strtoull(optarg, nullptr, 0);
      break;
    default:
      std::cerr << "Unkown argument: " << c << " " << std::endl;
      usage();
    }
  }

  if (!l) {
    std::cerr << "l not set." << std::endl;
    usage();
  }

  awgn_simulation(uncoded(l), 0.5, seed)();
}
<commit_msg>Use std::exit<commit_after>#include <iostream>
#include <cstdlib>

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <getopt.h>

#include "codes/uncoded.h"
#include "simulation/simulation.h"

[[noreturn]] static void usage() {
  std::cout << "--l <num>        "
            << "  "
            << "Choose code length l" << std::endl;
  std::cout << "--seed <num>     "
            << "  "
            << "Set seed of the random number generator." << std::endl;
  std::exit(EXIT_FAILURE);
}

int main(int argc, char *const argv[]) {
  unsigned long l = 0;
  uint64_t seed = 0;

  while (1) {
    static struct option options[] = {
      { "l", required_argument, nullptr, 'l' },
      { "seed", required_argument, nullptr, 's' },
      { nullptr, 0, nullptr, 0 },
    };

    int option_index = 0;
    int c = getopt_long_only(argc, argv, "", options, &option_index);
    if (c == -1)
      break;

    switch (c) {
    case 'l':
      l = strtoul(optarg, nullptr, 0);
      break;
    case 's':
      seed = strtoull(optarg, nullptr, 0);
      break;
    default:
      std::cerr << "Unkown argument: " << c << " " << std::endl;
      usage();
    }
  }

  if (!l) {
    std::cerr << "l not set." << std::endl;
    usage();
  }

  awgn_simulation(uncoded(l), 0.5, seed)();
}
<|endoftext|>


<commit_before>#include "Updates.hpp"

#include "common/NetworkRequest.hpp"
#include "common/Outcome.hpp"
#include "common/Version.hpp"
#include "singletons/Paths.hpp"
#include "util/CombinePath.hpp"
#include "util/PostToThread.hpp"

#include <QDebug>
#include <QDesktopServices>
#include <QMessageBox>
#include <QProcess>

namespace chatterino {

Updates::Updates()
    : currentVersion_(CHATTERINO_VERSION)
    , updateGuideLink_("https://chatterino.com")
{
    qDebug() << "init UpdateManager";
}

Updates &Updates::getInstance()
{
    // fourtf: don't add this class to the application class
    static Updates instance;

    return instance;
}

const QString &Updates::getCurrentVersion() const
{
    return currentVersion_;
}

const QString &Updates::getOnlineVersion() const
{
    return onlineVersion_;
}

void Updates::installUpdates()
{
    if (this->status_ != UpdateAvailable)
    {
        assert(false);
        return;
    }

#ifdef Q_OS_MACOS
    QMessageBox *box = new QMessageBox(
        QMessageBox::Information, "Chatterino Update",
        "A link will open in your browser. Download and install to update.");
    box->setAttribute(Qt::WA_DeleteOnClose);
    box->exec();
    QDesktopServices::openUrl(this->updateExe_);
#elif defined Q_OS_LINUX
    QMessageBox *box =
        new QMessageBox(QMessageBox::Information, "Chatterino Update",
                        "Automatic updates are currently not available on "
                        "linux. Please redownload the app to update.");
    box->setAttribute(Qt::WA_DeleteOnClose);
    box->exec();
    QDesktopServices::openUrl(this->updateGuideLink_);
#elif defined Q_OS_WIN
    if (getPaths()->isPortable())
    {
        QMessageBox *box =
            new QMessageBox(QMessageBox::Information, "Chatterino Update",
                            "Chatterino is downloading the update "
                            "in the background and will run the "
                            "updater once it is finished.");
        box->setAttribute(Qt::WA_DeleteOnClose);
        box->show();

        NetworkRequest(this->updatePortable_)
            .timeout(600000)
            .onError([this](int) -> bool {
                this->setStatus_(DownloadFailed);

                postToThread([] {
                    QMessageBox *box = new QMessageBox(
                        QMessageBox::Information, "Chatterino Update",
                        "Failed while trying to download the update.");
                    box->setAttribute(Qt::WA_DeleteOnClose);
                    box->show();
                    box->raise();
                });

                return true;
            })
            .onSuccess([this](auto result) -> Outcome {
                QByteArray object = result.getData();
                auto filename =
                    combinePath(getPaths()->miscDirectory, "update.zip");

                QFile file(filename);
                file.open(QIODevice::Truncate | QIODevice::WriteOnly);

                if (file.write(object) == -1)
                {
                    this->setStatus_(WriteFileFailed);
                    return Failure;
                }

                QProcess::startDetached(
                    combinePath(QCoreApplication::applicationDirPath(),
                                "updater.1/ChatterinoUpdater.exe"),
                    {filename, "restart"});

                QApplication::exit(0);
                return Success;
            })
            .execute();
        this->setStatus_(Downloading);
    }
    else
    {
        QMessageBox *box =
            new QMessageBox(QMessageBox::Information, "Chatterino Update",
                            "Chatterino is downloading the update "
                            "in the background and will run the "
                            "updater once it is finished.");
        box->setAttribute(Qt::WA_DeleteOnClose);
        box->show();

        NetworkRequest(this->updateExe_)
            .timeout(600000)
            .onError([this](int) -> bool {
                this->setStatus_(DownloadFailed);

                QMessageBox *box = new QMessageBox(
                    QMessageBox::Information, "Chatterino Update",
                    "Failed to download the update. \n\nTry manually "
                    "downloading the update.");
                box->setAttribute(Qt::WA_DeleteOnClose);
                box->exec();
                return true;
            })
            .onSuccess([this](auto result) -> Outcome {
                QByteArray object = result.getData();
                auto filename =
                    combinePath(getPaths()->miscDirectory, "Update.exe");

                QFile file(filename);
                file.open(QIODevice::Truncate | QIODevice::WriteOnly);

                if (file.write(object) == -1)
                {
                    this->setStatus_(WriteFileFailed);
                    QMessageBox *box = new QMessageBox(
                        QMessageBox::Information, "Chatterino Update",
                        "Failed to save the update file. This could be due to "
                        "window settings or antivirus software.\n\nTry "
                        "manually "
                        "downloading the update.");
                    box->setAttribute(Qt::WA_DeleteOnClose);
                    box->exec();

                    QDesktopServices::openUrl(this->updateExe_);
                    return Failure;
                }
                file.close();

                if (QProcess::startDetached(filename))
                {
                    QApplication::exit(0);
                }
                else
                {
                    QMessageBox *box = new QMessageBox(
                        QMessageBox::Information, "Chatterino Update",
                        "Failed to execute update binary. This could be due to "
                        "window "
                        "settings or antivirus software.\n\nTry manually "
                        "downloading "
                        "the update.");
                    box->setAttribute(Qt::WA_DeleteOnClose);
                    box->exec();

                    QDesktopServices::openUrl(this->updateExe_);
                }

                return Success;
            })
            .execute();
        this->setStatus_(Downloading);
    }
#endif
}

void Updates::checkForUpdates()
{
    QString url =
        "https://notitia.chatterino.com/version/chatterino/" CHATTERINO_OS
        "/stable";

    NetworkRequest(url)
        .timeout(60000)
        .onSuccess([this](auto result) -> Outcome {
            auto object = result.parseJson();
            /// Version available on every platform
            QJsonValue version_val = object.value("version");

            if (!version_val.isString())
            {
                this->setStatus_(SearchFailed);
                qDebug() << "error updating";
                return Failure;
            }

#if defined Q_OS_WIN || defined Q_OS_MACOS
            /// Windows downloads an installer for the new version
            QJsonValue updateExe_val = object.value("updateexe");
            if (!updateExe_val.isString())
            {
                this->setStatus_(SearchFailed);
                qDebug() << "error updating";
                return Failure;
            }
            this->updateExe_ = updateExe_val.toString();

            /// Windows portable
            QJsonValue portable_val = object.value("portable_download");
            if (!portable_val.isString())
            {
                this->setStatus_(SearchFailed);
                qDebug() << "error updating";
                return Failure;
            }
            this->updatePortable_ = portable_val.toString();

#elif defined Q_OS_LINUX
            QJsonValue updateGuide_val = object.value("updateguide");
            if (updateGuide_val.isString())
            {
                this->updateGuideLink_ = updateGuide_val.toString();
            }
#else
            return Failure;
#endif

            /// Current version
            this->onlineVersion_ = version_val.toString();

            /// Update available :)
            if (this->currentVersion_ != this->onlineVersion_)
            {
                this->setStatus_(UpdateAvailable);
            }
            else
            {
                this->setStatus_(NoUpdateAvailable);
            }
            return Failure;
        })
        .execute();
    this->setStatus_(Searching);
}

Updates::Status Updates::getStatus() const
{
    return this->status_;
}

bool Updates::shouldShowUpdateButton() const
{
    switch (this->getStatus())
    {
        case UpdateAvailable:
        case SearchFailed:
        case Downloading:
        case DownloadFailed:
        case WriteFileFailed:
            return true;

        default:
            return false;
    }
}

bool Updates::isError() const
{
    switch (this->getStatus())
    {
        case SearchFailed:
        case DownloadFailed:
        case WriteFileFailed:
            return true;

        default:
            return false;
    }
}

void Updates::setStatus_(Status status)
{
    if (this->status_ != status)
    {
        this->status_ = status;
        postToThread([this, status] { this->statusUpdated.invoke(status); });
    }
}

}  // namespace chatterino
<commit_msg>added some flush() calls just to be sure<commit_after>#include "Updates.hpp"

#include "common/NetworkRequest.hpp"
#include "common/Outcome.hpp"
#include "common/Version.hpp"
#include "singletons/Paths.hpp"
#include "util/CombinePath.hpp"
#include "util/PostToThread.hpp"

#include <QDebug>
#include <QDesktopServices>
#include <QMessageBox>
#include <QProcess>

namespace chatterino {

Updates::Updates()
    : currentVersion_(CHATTERINO_VERSION)
    , updateGuideLink_("https://chatterino.com")
{
    qDebug() << "init UpdateManager";
}

Updates &Updates::getInstance()
{
    // fourtf: don't add this class to the application class
    static Updates instance;

    return instance;
}

const QString &Updates::getCurrentVersion() const
{
    return currentVersion_;
}

const QString &Updates::getOnlineVersion() const
{
    return onlineVersion_;
}

void Updates::installUpdates()
{
    if (this->status_ != UpdateAvailable)
    {
        assert(false);
        return;
    }

#ifdef Q_OS_MACOS
    QMessageBox *box = new QMessageBox(
        QMessageBox::Information, "Chatterino Update",
        "A link will open in your browser. Download and install to update.");
    box->setAttribute(Qt::WA_DeleteOnClose);
    box->exec();
    QDesktopServices::openUrl(this->updateExe_);
#elif defined Q_OS_LINUX
    QMessageBox *box =
        new QMessageBox(QMessageBox::Information, "Chatterino Update",
                        "Automatic updates are currently not available on "
                        "linux. Please redownload the app to update.");
    box->setAttribute(Qt::WA_DeleteOnClose);
    box->exec();
    QDesktopServices::openUrl(this->updateGuideLink_);
#elif defined Q_OS_WIN
    if (getPaths()->isPortable())
    {
        QMessageBox *box =
            new QMessageBox(QMessageBox::Information, "Chatterino Update",
                            "Chatterino is downloading the update "
                            "in the background and will run the "
                            "updater once it is finished.");
        box->setAttribute(Qt::WA_DeleteOnClose);
        box->show();

        NetworkRequest(this->updatePortable_)
            .timeout(600000)
            .onError([this](int) -> bool {
                this->setStatus_(DownloadFailed);

                postToThread([] {
                    QMessageBox *box = new QMessageBox(
                        QMessageBox::Information, "Chatterino Update",
                        "Failed while trying to download the update.");
                    box->setAttribute(Qt::WA_DeleteOnClose);
                    box->show();
                    box->raise();
                });

                return true;
            })
            .onSuccess([this](auto result) -> Outcome {
                QByteArray object = result.getData();
                auto filename =
                    combinePath(getPaths()->miscDirectory, "update.zip");

                QFile file(filename);
                file.open(QIODevice::Truncate | QIODevice::WriteOnly);

                if (file.write(object) == -1)
                {
                    this->setStatus_(WriteFileFailed);
                    return Failure;
                }
                file.flush();
                file.close();

                QProcess::startDetached(
                    combinePath(QCoreApplication::applicationDirPath(),
                                "updater.1/ChatterinoUpdater.exe"),
                    {filename, "restart"});

                QApplication::exit(0);
                return Success;
            })
            .execute();
        this->setStatus_(Downloading);
    }
    else
    {
        QMessageBox *box =
            new QMessageBox(QMessageBox::Information, "Chatterino Update",
                            "Chatterino is downloading the update "
                            "in the background and will run the "
                            "updater once it is finished.");
        box->setAttribute(Qt::WA_DeleteOnClose);
        box->show();

        NetworkRequest(this->updateExe_)
            .timeout(600000)
            .onError([this](int) -> bool {
                this->setStatus_(DownloadFailed);

                QMessageBox *box = new QMessageBox(
                    QMessageBox::Information, "Chatterino Update",
                    "Failed to download the update. \n\nTry manually "
                    "downloading the update.");
                box->setAttribute(Qt::WA_DeleteOnClose);
                box->exec();
                return true;
            })
            .onSuccess([this](auto result) -> Outcome {
                QByteArray object = result.getData();
                auto filename =
                    combinePath(getPaths()->miscDirectory, "Update.exe");

                QFile file(filename);
                file.open(QIODevice::Truncate | QIODevice::WriteOnly);

                if (file.write(object) == -1)
                {
                    this->setStatus_(WriteFileFailed);
                    QMessageBox *box = new QMessageBox(
                        QMessageBox::Information, "Chatterino Update",
                        "Failed to save the update file. This could be due to "
                        "window settings or antivirus software.\n\nTry "
                        "manually "
                        "downloading the update.");
                    box->setAttribute(Qt::WA_DeleteOnClose);
                    box->exec();

                    QDesktopServices::openUrl(this->updateExe_);
                    return Failure;
                }
                file.flush();
                file.close();

                if (QProcess::startDetached(filename))
                {
                    QApplication::exit(0);
                }
                else
                {
                    QMessageBox *box = new QMessageBox(
                        QMessageBox::Information, "Chatterino Update",
                        "Failed to execute update binary. This could be due to "
                        "window "
                        "settings or antivirus software.\n\nTry manually "
                        "downloading "
                        "the update.");
                    box->setAttribute(Qt::WA_DeleteOnClose);
                    box->exec();

                    QDesktopServices::openUrl(this->updateExe_);
                }

                return Success;
            })
            .execute();
        this->setStatus_(Downloading);
    }
#endif
}

void Updates::checkForUpdates()
{
    QString url =
        "https://notitia.chatterino.com/version/chatterino/" CHATTERINO_OS
        "/stable";

    NetworkRequest(url)
        .timeout(60000)
        .onSuccess([this](auto result) -> Outcome {
            auto object = result.parseJson();
            /// Version available on every platform
            QJsonValue version_val = object.value("version");

            if (!version_val.isString())
            {
                this->setStatus_(SearchFailed);
                qDebug() << "error updating";
                return Failure;
            }

#if defined Q_OS_WIN || defined Q_OS_MACOS
            /// Windows downloads an installer for the new version
            QJsonValue updateExe_val = object.value("updateexe");
            if (!updateExe_val.isString())
            {
                this->setStatus_(SearchFailed);
                qDebug() << "error updating";
                return Failure;
            }
            this->updateExe_ = updateExe_val.toString();

            /// Windows portable
            QJsonValue portable_val = object.value("portable_download");
            if (!portable_val.isString())
            {
                this->setStatus_(SearchFailed);
                qDebug() << "error updating";
                return Failure;
            }
            this->updatePortable_ = portable_val.toString();

#elif defined Q_OS_LINUX
            QJsonValue updateGuide_val = object.value("updateguide");
            if (updateGuide_val.isString())
            {
                this->updateGuideLink_ = updateGuide_val.toString();
            }
#else
            return Failure;
#endif

            /// Current version
            this->onlineVersion_ = version_val.toString();

            /// Update available :)
            if (this->currentVersion_ != this->onlineVersion_)
            {
                this->setStatus_(UpdateAvailable);
            }
            else
            {
                this->setStatus_(NoUpdateAvailable);
            }
            return Failure;
        })
        .execute();
    this->setStatus_(Searching);
}

Updates::Status Updates::getStatus() const
{
    return this->status_;
}

bool Updates::shouldShowUpdateButton() const
{
    switch (this->getStatus())
    {
        case UpdateAvailable:
        case SearchFailed:
        case Downloading:
        case DownloadFailed:
        case WriteFileFailed:
            return true;

        default:
            return false;
    }
}

bool Updates::isError() const
{
    switch (this->getStatus())
    {
        case SearchFailed:
        case DownloadFailed:
        case WriteFileFailed:
            return true;

        default:
            return false;
    }
}

void Updates::setStatus_(Status status)
{
    if (this->status_ != status)
    {
        this->status_ = status;
        postToThread([this, status] { this->statusUpdated.invoke(status); });
    }
}

}  // namespace chatterino
<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Infrastructure 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

#include "anomaly_serv.hpp"

#include <string>
#include <utility>
#include <vector>
#include "jubatus/server/common/logger/logger.hpp"
#include "jubatus/util/concurrent/lock.h"
#include "jubatus/util/text/json.h"
#include "jubatus/util/lang/shared_ptr.h"

#include "jubatus/core/common/assert.hpp"
#include "jubatus/core/common/vector_util.hpp"
#include "jubatus/core/common/jsonconfig.hpp"
#include "jubatus/core/fv_converter/datum.hpp"
#include "jubatus/core/fv_converter/datum_to_fv_converter.hpp"
#include "jubatus/core/fv_converter/converter_config.hpp"
#include "jubatus/core/anomaly/anomaly_factory.hpp"

#include "../common/global_id_generator_standalone.hpp"
#ifdef HAVE_ZOOKEEPER_H
#include "../common/cht.hpp"
#include "../common/global_id_generator_zk.hpp"
#include "../common/membership.hpp"
#endif
#include "../framework/mixer/mixer_factory.hpp"
#include "anomaly_client.hpp"

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

using std::string;
using std::vector;
using std::pair;
using jubatus::util::lang::lexical_cast;
using jubatus::util::text::json::json;
using jubatus::core::fv_converter::datum;
using jubatus::server::common::lock_service;
using jubatus::server::framework::server_argv;
using jubatus::server::framework::mixer::create_mixer;

namespace jubatus {
namespace server {

namespace {

struct anomaly_serv_config {
  std::string method;
  // TODO(oda): we should use optional<jsonconfig::config> instead of
  //            jsonconfig::config ?
  core::common::jsonconfig::config parameter;
  core::fv_converter::converter_config converter;

  template<typename Ar>
  void serialize(Ar& ar) {
    ar & JUBA_MEMBER(method) & JUBA_MEMBER(parameter) & JUBA_MEMBER(converter);
  }
};

}  // namespace

anomaly_serv::anomaly_serv(
    const server_argv& a,
    const jubatus::util::lang::shared_ptr<lock_service>& zk)
    : server_base(a),
      mixer_(create_mixer(a, zk, rw_mutex())) {
#ifdef HAVE_ZOOKEEPER_H
  if (a.is_standalone()) {
#endif
    idgen_.reset(new common::global_id_generator_standalone());
#ifdef HAVE_ZOOKEEPER_H
  } else {
    zk_ = zk;
    common::global_id_generator_zk* idgen_zk =
        new common::global_id_generator_zk();
    idgen_.reset(idgen_zk);

    string counter_path;
    common::build_actor_path(counter_path, a.type, a.name);
    idgen_zk->set_ls(zk_, counter_path);
  }
#endif
}

anomaly_serv::~anomaly_serv() {
}

void anomaly_serv::get_status(status_t& status) const {
  status_t my_status;
  my_status["storage"] = anomaly_->get_model()->type();

  status.insert(my_status.begin(), my_status.end());
}

uint64_t anomaly_serv::user_data_version() const {
  return 1;  // should be inclemented when model data is modified
}

void anomaly_serv::set_config(const std::string& config) {
  core::common::jsonconfig::config conf_root(lexical_cast<json>(config));
  anomaly_serv_config conf =
    core::common::jsonconfig::config_cast_check<anomaly_serv_config>(conf_root);

  config_ = config;

#if 0
  // TODO(oda): we should use optional<jsonconfig::config> instead of
  //            jsonconfig::config ?

  jsonconfig::config param;
  if (conf.parameter) {
    param = *conf.parameter;
  }
#endif

  std::string my_id;
#ifdef HAVE_ZOOKEEPER_H
  my_id = common::build_loc_str(argv().eth, argv().port);
#endif

  anomaly_.reset(
      new core::driver::anomaly(
          core::anomaly::anomaly_factory::create_anomaly(
              conf.method, conf.parameter, my_id),
          core::fv_converter::make_fv_converter(conf.converter, &so_loader_)));
  mixer_->set_driver(anomaly_.get());

  LOG(INFO) << "config loaded: " << config;
}

string anomaly_serv::get_config() const {
  check_set_config();
  return config_;
}

bool anomaly_serv::clear_row(const string& id) {
  check_set_config();
  anomaly_->clear_row(id);
  DLOG(INFO) << "row cleared: " << id;
  return true;
}

// nolock, random
id_with_score anomaly_serv::add(const datum& data) {
  check_set_config();

  uint64_t id = idgen_->generate();
  string id_str = jubatus::util::lang::lexical_cast<string>(id);

#ifdef HAVE_ZOOKEEPER_H
  if (argv().is_standalone()) {
#endif
    jubatus::util::concurrent::scoped_wlock lk(rw_mutex());
    event_model_updated();
    // TODO(unno): remove conversion code
    pair<string, float> res = anomaly_->add(id_str, data);
    return id_with_score(res.first, res.second);
#ifdef HAVE_ZOOKEEPER_H
  } else {
    return add_zk(id_str, data);
  }
#endif
}

id_with_score anomaly_serv::add_zk(const string&id_str, const datum& d) {
  vector<pair<string, int> > nodes;
  float score = 0;
  find_from_cht(id_str, 2, nodes);
  if (nodes.empty()) {
    throw JUBATUS_EXCEPTION(
      core::common::membership_error("no server found in cht: " + argv().name));
  }
  // this sequences MUST success,
  // in case of failures the whole request should be canceled
  DLOG(INFO) << "initial add request to "
             << nodes[0].first << ":" << nodes[0].second;
  try {
    score = selective_update(nodes[0].first, nodes[0].second, id_str, d);
  } catch (const std::runtime_error& e) {
    throw JUBATUS_EXCEPTION(core::common::exception::runtime_error(
        "failed to add ID " + id_str + " (" + e.what() + "): " +
            nodes[0].first + ":" + lexical_cast<string>(nodes[0].second)));
  }

  for (size_t i = 1; i < nodes.size(); ++i) {
    DLOG(INFO) << "replica add request to "
               << nodes[i].first << ":" << nodes[i].second;
    try {
      selective_update(nodes[i].first, nodes[i].second, id_str, d);
    } catch (const std::runtime_error& e) {
      LOG(WARNING) << "cannot create " << i << "th replica "
                   << "(" << e.what() << "): "
                   << nodes[i].first << ":" << nodes[i].second;
    }
  }
  DLOG(INFO) << "point added: " << id_str;
  return id_with_score(id_str, score);
}

float anomaly_serv::update(const string& id, const datum& data) {
  check_set_config();

  float score = anomaly_->update(id, data);
  DLOG(INFO) << "point updated: " << id;
  return score;
}

float anomaly_serv::overwrite(const string& id, const datum& data) {
  check_set_config();

  float score = anomaly_->overwrite(id, data);
  DLOG(INFO) << "point overwritten: " << id;
  return score;
}

bool anomaly_serv::clear() {
  check_set_config();
  anomaly_->clear();
  LOG(INFO) << "model cleared: " << argv().name;
  return true;
}

float anomaly_serv::calc_score(const datum& data) const {
  check_set_config();
  return anomaly_->calc_score(data);
}

vector<string> anomaly_serv::get_all_rows() const {
  check_set_config();
  return anomaly_->get_all_rows();
}

void anomaly_serv::check_set_config() const {
  if (!anomaly_) {
    throw JUBATUS_EXCEPTION(core::common::config_not_set());
  }
}

void anomaly_serv::find_from_cht(
    const string& key,
    size_t n,
    vector<pair<string, int> >& out) {
  out.clear();
#ifdef HAVE_ZOOKEEPER_H
  common::cht ht(zk_, argv().type, argv().name);
  ht.find(key, out, n);  // replication number of local_node
#else
  // cannot reach here, assertion!
  JUBATUS_ASSERT_UNREACHABLE();
  // JUBATUS_ASSERT(argv().is_standalone());
  // out.push_back(make_pair(argv().eth, argv().port));
#endif
}

/*
 * Updates the model on the specified node and returns the score.
 * If the host/port of the current process is specified, update
 * is processed locally.
 * Caller is responsible for handling exceptions including RPC
 * errors.
 */
float anomaly_serv::selective_update(
    const string& host,
    int port,
    const string& id,
    const datum& d) {
  // nolock context
  if (host == argv().eth && port == argv().port) {
    jubatus::util::concurrent::scoped_wlock lk(rw_mutex());
    event_model_updated();
    return this->update(id, d);
  } else {  // needs no lock
    client::anomaly c(host, port, argv().name, argv().interconnect_timeout);
    return c.update(id, d);
  }
}

bool anomaly_serv::load(const std::string& id) {
  if (server_base::load(id)) {
    reset_id_generator();
    return true;
  }
  return false;
}

void anomaly_serv::load_file(const std::string& path) {
  server_base::load_file(path);
  reset_id_generator();
}

void anomaly_serv::reset_id_generator() {
  if (argv().is_standalone()) {
    uint64_t counter = anomaly_->find_max_int_id() + 1;
    idgen_.reset(
        new common::global_id_generator_standalone(counter));
  } else {
    // TODO(hido): support ID check for distributed mode
  }
}

}  // namespace server
}  // namespace jubatus
<commit_msg>Call overwrite instead of update when is_updatable() == false<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Infrastructure 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

#include "anomaly_serv.hpp"

#include <string>
#include <utility>
#include <vector>
#include "jubatus/server/common/logger/logger.hpp"
#include "jubatus/util/concurrent/lock.h"
#include "jubatus/util/text/json.h"
#include "jubatus/util/lang/shared_ptr.h"

#include "jubatus/core/common/assert.hpp"
#include "jubatus/core/common/vector_util.hpp"
#include "jubatus/core/common/jsonconfig.hpp"
#include "jubatus/core/fv_converter/datum.hpp"
#include "jubatus/core/fv_converter/datum_to_fv_converter.hpp"
#include "jubatus/core/fv_converter/converter_config.hpp"
#include "jubatus/core/anomaly/anomaly_factory.hpp"

#include "../common/global_id_generator_standalone.hpp"
#ifdef HAVE_ZOOKEEPER_H
#include "../common/cht.hpp"
#include "../common/global_id_generator_zk.hpp"
#include "../common/membership.hpp"
#endif
#include "../framework/mixer/mixer_factory.hpp"
#include "anomaly_client.hpp"

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

using std::string;
using std::vector;
using std::pair;
using jubatus::util::lang::lexical_cast;
using jubatus::util::text::json::json;
using jubatus::core::fv_converter::datum;
using jubatus::server::common::lock_service;
using jubatus::server::framework::server_argv;
using jubatus::server::framework::mixer::create_mixer;

namespace jubatus {
namespace server {

namespace {

struct anomaly_serv_config {
  std::string method;
  // TODO(oda): we should use optional<jsonconfig::config> instead of
  //            jsonconfig::config ?
  core::common::jsonconfig::config parameter;
  core::fv_converter::converter_config converter;

  template<typename Ar>
  void serialize(Ar& ar) {
    ar & JUBA_MEMBER(method) & JUBA_MEMBER(parameter) & JUBA_MEMBER(converter);
  }
};

}  // namespace

anomaly_serv::anomaly_serv(
    const server_argv& a,
    const jubatus::util::lang::shared_ptr<lock_service>& zk)
    : server_base(a),
      mixer_(create_mixer(a, zk, rw_mutex())) {
#ifdef HAVE_ZOOKEEPER_H
  if (a.is_standalone()) {
#endif
    idgen_.reset(new common::global_id_generator_standalone());
#ifdef HAVE_ZOOKEEPER_H
  } else {
    zk_ = zk;
    common::global_id_generator_zk* idgen_zk =
        new common::global_id_generator_zk();
    idgen_.reset(idgen_zk);

    string counter_path;
    common::build_actor_path(counter_path, a.type, a.name);
    idgen_zk->set_ls(zk_, counter_path);
  }
#endif
}

anomaly_serv::~anomaly_serv() {
}

void anomaly_serv::get_status(status_t& status) const {
  status_t my_status;
  my_status["storage"] = anomaly_->get_model()->type();

  status.insert(my_status.begin(), my_status.end());
}

uint64_t anomaly_serv::user_data_version() const {
  return 1;  // should be inclemented when model data is modified
}

void anomaly_serv::set_config(const std::string& config) {
  core::common::jsonconfig::config conf_root(lexical_cast<json>(config));
  anomaly_serv_config conf =
    core::common::jsonconfig::config_cast_check<anomaly_serv_config>(conf_root);

  config_ = config;

#if 0
  // TODO(oda): we should use optional<jsonconfig::config> instead of
  //            jsonconfig::config ?

  jsonconfig::config param;
  if (conf.parameter) {
    param = *conf.parameter;
  }
#endif

  std::string my_id;
#ifdef HAVE_ZOOKEEPER_H
  my_id = common::build_loc_str(argv().eth, argv().port);
#endif

  anomaly_.reset(
      new core::driver::anomaly(
          core::anomaly::anomaly_factory::create_anomaly(
              conf.method, conf.parameter, my_id),
          core::fv_converter::make_fv_converter(conf.converter, &so_loader_)));
  mixer_->set_driver(anomaly_.get());

  LOG(INFO) << "config loaded: " << config;
}

string anomaly_serv::get_config() const {
  check_set_config();
  return config_;
}

bool anomaly_serv::clear_row(const string& id) {
  check_set_config();
  anomaly_->clear_row(id);
  DLOG(INFO) << "row cleared: " << id;
  return true;
}

// nolock, random
id_with_score anomaly_serv::add(const datum& data) {
  check_set_config();

  uint64_t id = idgen_->generate();
  string id_str = jubatus::util::lang::lexical_cast<string>(id);

#ifdef HAVE_ZOOKEEPER_H
  if (argv().is_standalone()) {
#endif
    jubatus::util::concurrent::scoped_wlock lk(rw_mutex());
    event_model_updated();
    // TODO(unno): remove conversion code
    pair<string, float> res = anomaly_->add(id_str, data);
    return id_with_score(res.first, res.second);
#ifdef HAVE_ZOOKEEPER_H
  } else {
    return add_zk(id_str, data);
  }
#endif
}

id_with_score anomaly_serv::add_zk(const string&id_str, const datum& d) {
  vector<pair<string, int> > nodes;
  float score = 0;
  find_from_cht(id_str, 2, nodes);
  if (nodes.empty()) {
    throw JUBATUS_EXCEPTION(
      core::common::membership_error("no server found in cht: " + argv().name));
  }
  // this sequences MUST success,
  // in case of failures the whole request should be canceled
  DLOG(INFO) << "initial add request to "
             << nodes[0].first << ":" << nodes[0].second;
  try {
    score = selective_update(nodes[0].first, nodes[0].second, id_str, d);
  } catch (const std::runtime_error& e) {
    throw JUBATUS_EXCEPTION(core::common::exception::runtime_error(
        "failed to add ID " + id_str + " (" + e.what() + "): " +
            nodes[0].first + ":" + lexical_cast<string>(nodes[0].second)));
  }

  for (size_t i = 1; i < nodes.size(); ++i) {
    DLOG(INFO) << "replica add request to "
               << nodes[i].first << ":" << nodes[i].second;
    try {
      selective_update(nodes[i].first, nodes[i].second, id_str, d);
    } catch (const std::runtime_error& e) {
      LOG(WARNING) << "cannot create " << i << "th replica "
                   << "(" << e.what() << "): "
                   << nodes[i].first << ":" << nodes[i].second;
    }
  }
  DLOG(INFO) << "point added: " << id_str;
  return id_with_score(id_str, score);
}

float anomaly_serv::update(const string& id, const datum& data) {
  check_set_config();

  float score = anomaly_->update(id, data);
  DLOG(INFO) << "point updated: " << id;
  return score;
}

float anomaly_serv::overwrite(const string& id, const datum& data) {
  check_set_config();

  float score = anomaly_->overwrite(id, data);
  DLOG(INFO) << "point overwritten: " << id;
  return score;
}

bool anomaly_serv::clear() {
  check_set_config();
  anomaly_->clear();
  LOG(INFO) << "model cleared: " << argv().name;
  return true;
}

float anomaly_serv::calc_score(const datum& data) const {
  check_set_config();
  return anomaly_->calc_score(data);
}

vector<string> anomaly_serv::get_all_rows() const {
  check_set_config();
  return anomaly_->get_all_rows();
}

void anomaly_serv::check_set_config() const {
  if (!anomaly_) {
    throw JUBATUS_EXCEPTION(core::common::config_not_set());
  }
}

void anomaly_serv::find_from_cht(
    const string& key,
    size_t n,
    vector<pair<string, int> >& out) {
  out.clear();
#ifdef HAVE_ZOOKEEPER_H
  common::cht ht(zk_, argv().type, argv().name);
  ht.find(key, out, n);  // replication number of local_node
#else
  // cannot reach here, assertion!
  JUBATUS_ASSERT_UNREACHABLE();
  // JUBATUS_ASSERT(argv().is_standalone());
  // out.push_back(make_pair(argv().eth, argv().port));
#endif
}

/*
 * Updates the model on the specified node and returns the score.
 * If the host/port of the current process is specified, update
 * is processed locally.
 * Caller is responsible for handling exceptions including RPC
 * errors.
 */
float anomaly_serv::selective_update(
    const string& host,
    int port,
    const string& id,
    const datum& d) {
  // nolock context
  if (host == argv().eth && port == argv().port) {
    jubatus::util::concurrent::scoped_wlock lk(rw_mutex());
    event_model_updated();
    if (anomaly_->is_updatable()) {
      return this->update(id, d);
    } else {
      return this->overwrite(id, d);
    }
  } else {  // needs no lock
    client::anomaly c(host, port, argv().name, argv().interconnect_timeout);
    if (anomaly_->is_updatable()) {
      return c.update(id, d);
    } else {
      return c.overwrite(id, d);
    }
  }
}

bool anomaly_serv::load(const std::string& id) {
  if (server_base::load(id)) {
    reset_id_generator();
    return true;
  }
  return false;
}

void anomaly_serv::load_file(const std::string& path) {
  server_base::load_file(path);
  reset_id_generator();
}

void anomaly_serv::reset_id_generator() {
  if (argv().is_standalone()) {
    uint64_t counter = anomaly_->find_max_int_id() + 1;
    idgen_.reset(
        new common::global_id_generator_standalone(counter));
  } else {
    // TODO(hido): support ID check for distributed mode
  }
}

}  // namespace server
}  // namespace jubatus
<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011 Preferred Infrastructure 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

#include "util.hpp"

#include <arpa/inet.h>
#ifdef __APPLE__
#include <libproc.h>
#endif
#include <net/if.h>
#include <netinet/in.h>
#include <pwd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>

#include <cerrno>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <csignal>
#include <fstream>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include <glog/logging.h>
#include <pficommon/lang/exception.h>
#include <pficommon/text/json.h>

#include "jubatus/core/common/exception.hpp"

using std::string;
using pfi::lang::lexical_cast;
using pfi::lang::parse_error;

namespace jubatus {
namespace server {
namespace common {
namespace util {

// TODO(kashihara): AF_INET does not specify IPv6
void get_ip(const char* nic, string& out) {
  int fd;
  struct ifreq ifr;

  fd = socket(AF_INET, SOCK_DGRAM, 0);
  if (fd == -1) {
    throw JUBATUS_EXCEPTION(jubatus::core::common::exception::runtime_error(
          "Failed to create socket(AF_INET, SOCK_DGRAM)")
        << jubatus::core::common::exception::error_errno(errno));
  }

  ifr.ifr_addr.sa_family = AF_INET;
  strncpy(ifr.ifr_name, nic, IFNAMSIZ - 1);
  if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) {
    throw JUBATUS_EXCEPTION(jubatus::core::common::exception::runtime_error(
          "Failed to get IP address from interface")
        << jubatus::core::common::exception::error_errno(errno));
  }
  close(fd);

  struct sockaddr_in* sin = (struct sockaddr_in*) (&(ifr.ifr_addr));
  out = inet_ntoa((struct in_addr) (sin->sin_addr));
}

string get_ip(const char* nic) {
  string ret;
  get_ip(nic, ret);
  return ret;
}

string base_name(const string& path) {
  size_t found = path.rfind('/');
  return found != string::npos ? path.substr(found + 1) : path;
}

std::string get_program_name() {
  // WARNING: this code will only work on linux or OS X
#ifdef __APPLE__
  char path[PROC_PIDPATHINFO_MAXSIZE];
  int ret = proc_pidpath(getpid(), path, PROC_PIDPATHINFO_MAXSIZE);
#else
  const char* exe_sym_path = "/proc/self/exe";
  // when BSD: /proc/curproc/file
  // when Solaris: /proc/self/path/a.out
  // Unix: getexecname(3)
  char path[PATH_MAX];
  ssize_t ret = readlink(exe_sym_path, path, PATH_MAX);
  if (ret != -1) {
    if (ret == PATH_MAX) {
      throw JUBATUS_EXCEPTION(jubatus::core::common::exception::runtime_error(
            "Failed to get program name. Path size overed PATH_MAX.")
          << jubatus::core::common::exception::error_errno(errno));
    }
    path[ret] = '\0';
  }
#endif
  if (ret < 0) {
    throw JUBATUS_EXCEPTION(
      core::common::exception::runtime_error("Failed to get program name")
      << core::common::exception::error_errno(errno));
  }

  // get basename
  const string program_base_name = base_name(path);
  if (program_base_name == path) {
    throw JUBATUS_EXCEPTION(jubatus::core::common::exception::runtime_error(
          string("Failed to get program name from path: ") + path)
        << jubatus::core::common::exception::error_file_name(path));
  }
  return program_base_name;
}

std::string get_user_name() {
  uid_t uid = getuid();
  int64_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
  std::vector<char> buf(buflen);
  struct passwd pwd;
  struct passwd* result;
  int ret = getpwuid_r(uid, &pwd, &buf[0], buflen, &result);
  if (ret == 0) {
    if (result != NULL) {
      return result->pw_name;
    }
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error("User not found")
      << core::common::exception::error_api_func("getpwuid_r"));
  }
  throw JUBATUS_EXCEPTION(
      jubatus::core::common::exception::runtime_error("Failed to get user name")
      << jubatus::core::common::exception::error_api_func("getpwuid_r")
      << jubatus::core::common::exception::error_errno(ret));
}

bool is_writable(const char* dir_path) {
  struct stat st_buf;
  if (stat(dir_path, &st_buf) < 0) {
    return false;
  }

  if (!S_ISDIR(st_buf.st_mode)) {
    errno = ENOTDIR;
    return false;
  }

  if (access(dir_path, W_OK) < 0) {
    return false;
  }

  return true;
}

int daemonize() {
  return daemon(0, 0);
}

void append_env_path(const string& e, const string& argv0) {
  const char* env = getenv(e.c_str());
  string new_path = string(env) + ":" + argv0;
  setenv(e.c_str(), new_path.c_str(), new_path.size());
}

void append_server_path(const string& argv0) {
  const char* env = getenv("PATH");
  char cwd[PATH_MAX];
  if (!getcwd(cwd, PATH_MAX)) {
    throw JUBATUS_EXCEPTION(
        jubatus::core::common::exception::runtime_error("Failed to getcwd"))
        << jubatus::core::common::exception::error_errno(errno);
  }

  string p = argv0.substr(0, argv0.find_last_of('/'));
  string new_path = string(env) + ":" + cwd + "/" + p + "/../server";
  setenv("PATH", new_path.c_str(), new_path.size());
}

void get_machine_status(machine_status_t& status) {
  // WARNING: this code will only work on linux
  try {
    // /proc/[pid]/statm shows using page size
    char path[64];
    snprintf(path, sizeof(path), "/proc/%d/statm", getpid());
    std::ifstream statm(path);

    const int64_t page_size = sysconf(_SC_PAGESIZE);
    uint64_t vm_virt, vm_rss, vm_shr;
    statm >> vm_virt >> vm_rss >> vm_shr;
    vm_virt = vm_virt * page_size / 1024;
    vm_rss = vm_rss * page_size / 1024;
    vm_shr = vm_shr * page_size / 1024;

    // in KB
    status.vm_size = vm_virt;  // total program size(virtual memory)
    status.vm_resident = vm_rss;  // resident set size
    status.vm_share = vm_shr;  // shared
  } catch (...) {
    // store zero
    status.vm_size = 0;
    status.vm_resident = 0;
    status.vm_share = 0;
  }
}

namespace {

void exit_on_term(int /* signum */) {
  LOG(INFO) << "stopping RPC server";
  exit(0);
}

}  // namespace

void set_exit_on_term() {
  struct sigaction sigact;
  sigact.sa_handler = exit_on_term;
  sigact.sa_flags = SA_RESTART;

  if (sigaction(SIGTERM, &sigact, NULL) != 0) {
    throw JUBATUS_EXCEPTION(
      core::common::exception::runtime_error("can't set SIGTERM handler")
      << core::common::exception::error_api_func("sigaction")
      << core::common::exception::error_errno(errno));
  }

  if (sigaction(SIGINT, &sigact, NULL) != 0) {
    throw JUBATUS_EXCEPTION(
      core::common::exception::runtime_error("can't set SIGINT handler")
      << core::common::exception::error_api_func("sigaction")
      << core::common::exception::error_errno(errno));
  }
}

void ignore_sigpipe() {
  // portable code for socket write(2) MSG_NOSIGNAL
  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
    throw JUBATUS_EXCEPTION(
        jubatus::core::common::exception::runtime_error("can't ignore SIGPIPE")
        << jubatus::core::common::exception::error_api_func("signal")
        << jubatus::core::common::exception::error_errno(errno));
  }
}

}  // namespace util
}  // namespace common
}  // namespace server
}  // namespace jubatus

<commit_msg>Remove catch clause which is never executed<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011 Preferred Infrastructure 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

#include "util.hpp"

#include <arpa/inet.h>
#ifdef __APPLE__
#include <libproc.h>
#endif
#include <net/if.h>
#include <netinet/in.h>
#include <pwd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>

#include <cerrno>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <csignal>
#include <fstream>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include <glog/logging.h>
#include <pficommon/lang/exception.h>
#include <pficommon/text/json.h>

#include "jubatus/core/common/exception.hpp"

using std::string;
using pfi::lang::lexical_cast;
using pfi::lang::parse_error;

namespace jubatus {
namespace server {
namespace common {
namespace util {

// TODO(kashihara): AF_INET does not specify IPv6
void get_ip(const char* nic, string& out) {
  int fd;
  struct ifreq ifr;

  fd = socket(AF_INET, SOCK_DGRAM, 0);
  if (fd == -1) {
    throw JUBATUS_EXCEPTION(jubatus::core::common::exception::runtime_error(
          "Failed to create socket(AF_INET, SOCK_DGRAM)")
        << jubatus::core::common::exception::error_errno(errno));
  }

  ifr.ifr_addr.sa_family = AF_INET;
  strncpy(ifr.ifr_name, nic, IFNAMSIZ - 1);
  if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) {
    throw JUBATUS_EXCEPTION(jubatus::core::common::exception::runtime_error(
          "Failed to get IP address from interface")
        << jubatus::core::common::exception::error_errno(errno));
  }
  close(fd);

  struct sockaddr_in* sin = (struct sockaddr_in*) (&(ifr.ifr_addr));
  out = inet_ntoa((struct in_addr) (sin->sin_addr));
}

string get_ip(const char* nic) {
  string ret;
  get_ip(nic, ret);
  return ret;
}

string base_name(const string& path) {
  size_t found = path.rfind('/');
  return found != string::npos ? path.substr(found + 1) : path;
}

std::string get_program_name() {
  // WARNING: this code will only work on linux or OS X
#ifdef __APPLE__
  char path[PROC_PIDPATHINFO_MAXSIZE];
  int ret = proc_pidpath(getpid(), path, PROC_PIDPATHINFO_MAXSIZE);
#else
  const char* exe_sym_path = "/proc/self/exe";
  // when BSD: /proc/curproc/file
  // when Solaris: /proc/self/path/a.out
  // Unix: getexecname(3)
  char path[PATH_MAX];
  ssize_t ret = readlink(exe_sym_path, path, PATH_MAX);
  if (ret != -1) {
    if (ret == PATH_MAX) {
      throw JUBATUS_EXCEPTION(jubatus::core::common::exception::runtime_error(
            "Failed to get program name. Path size overed PATH_MAX.")
          << jubatus::core::common::exception::error_errno(errno));
    }
    path[ret] = '\0';
  }
#endif
  if (ret < 0) {
    throw JUBATUS_EXCEPTION(
      core::common::exception::runtime_error("Failed to get program name")
      << core::common::exception::error_errno(errno));
  }

  // get basename
  const string program_base_name = base_name(path);
  if (program_base_name == path) {
    throw JUBATUS_EXCEPTION(jubatus::core::common::exception::runtime_error(
          string("Failed to get program name from path: ") + path)
        << jubatus::core::common::exception::error_file_name(path));
  }
  return program_base_name;
}

std::string get_user_name() {
  uid_t uid = getuid();
  int64_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
  std::vector<char> buf(buflen);
  struct passwd pwd;
  struct passwd* result;
  int ret = getpwuid_r(uid, &pwd, &buf[0], buflen, &result);
  if (ret == 0) {
    if (result != NULL) {
      return result->pw_name;
    }
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error("User not found")
      << core::common::exception::error_api_func("getpwuid_r"));
  }
  throw JUBATUS_EXCEPTION(
      jubatus::core::common::exception::runtime_error("Failed to get user name")
      << jubatus::core::common::exception::error_api_func("getpwuid_r")
      << jubatus::core::common::exception::error_errno(ret));
}

bool is_writable(const char* dir_path) {
  struct stat st_buf;
  if (stat(dir_path, &st_buf) < 0) {
    return false;
  }

  if (!S_ISDIR(st_buf.st_mode)) {
    errno = ENOTDIR;
    return false;
  }

  if (access(dir_path, W_OK) < 0) {
    return false;
  }

  return true;
}

int daemonize() {
  return daemon(0, 0);
}

void append_env_path(const string& e, const string& argv0) {
  const char* env = getenv(e.c_str());
  string new_path = string(env) + ":" + argv0;
  setenv(e.c_str(), new_path.c_str(), new_path.size());
}

void append_server_path(const string& argv0) {
  const char* env = getenv("PATH");
  char cwd[PATH_MAX];
  if (!getcwd(cwd, PATH_MAX)) {
    throw JUBATUS_EXCEPTION(
        jubatus::core::common::exception::runtime_error("Failed to getcwd"))
        << jubatus::core::common::exception::error_errno(errno);
  }

  string p = argv0.substr(0, argv0.find_last_of('/'));
  string new_path = string(env) + ":" + cwd + "/" + p + "/../server";
  setenv("PATH", new_path.c_str(), new_path.size());
}

void get_machine_status(machine_status_t& status) {
  // WARNING: this code will only work on linux
  uint64_t vm_virt = 0, vm_rss = 0, vm_shr = 0;

  // /proc/[pid]/statm shows using page size
  char path[64];
  snprintf(path, sizeof(path), "/proc/%d/statm", getpid());

  std::ifstream statm(path);
  if (statm) {
    const int64_t page_size = sysconf(_SC_PAGESIZE);
    statm >> vm_virt >> vm_rss >> vm_shr;
    vm_virt = vm_virt * page_size / 1024;
    vm_rss = vm_rss * page_size / 1024;
    vm_shr = vm_shr * page_size / 1024;
  }

  // in KB
  status.vm_size = vm_virt;  // total program size(virtual memory)
  status.vm_resident = vm_rss;  // resident set size
  status.vm_share = vm_shr;  // shared
}

namespace {

void exit_on_term(int /* signum */) {
  LOG(INFO) << "stopping RPC server";
  exit(0);
}

}  // namespace

void set_exit_on_term() {
  struct sigaction sigact;
  sigact.sa_handler = exit_on_term;
  sigact.sa_flags = SA_RESTART;

  if (sigaction(SIGTERM, &sigact, NULL) != 0) {
    throw JUBATUS_EXCEPTION(
      core::common::exception::runtime_error("can't set SIGTERM handler")
      << core::common::exception::error_api_func("sigaction")
      << core::common::exception::error_errno(errno));
  }

  if (sigaction(SIGINT, &sigact, NULL) != 0) {
    throw JUBATUS_EXCEPTION(
      core::common::exception::runtime_error("can't set SIGINT handler")
      << core::common::exception::error_api_func("sigaction")
      << core::common::exception::error_errno(errno));
  }
}

void ignore_sigpipe() {
  // portable code for socket write(2) MSG_NOSIGNAL
  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
    throw JUBATUS_EXCEPTION(
        jubatus::core::common::exception::runtime_error("can't ignore SIGPIPE")
        << jubatus::core::common::exception::error_api_func("signal")
        << jubatus::core::common::exception::error_errno(errno));
  }
}

}  // namespace util
}  // namespace common
}  // namespace server
}  // namespace jubatus

<|endoftext|>


<commit_before>/*
 *  Copyright 2010-2011 Anders Wallin (anders.e.e.wallin "at" gmail.com)
 *
 *  Idea and code for point/line/arc voronoi-vertex positioning code by
 *  Andy Payne, andy "at" payne "dot" org, November, 2010
 *  see: http://www.payne.org/index.php/Calculating_Voronoi_Nodes
 *
 *  This file is part of OpenVoronoi.
 *
 *  OpenVoronoi is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  OpenVoronoi is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with OpenVoronoi.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "common/point.hpp"
#include "common/numeric.hpp"

using namespace ovd::numeric; // sq() chop() determinant()

namespace ovd {
namespace solvers {

/// \brief line-line-line Solver
///
/// solves 3x3 system.
class LLLSolver : public Solver {
public:

//  a1 x + b1 y + c1 + k1 t = 0
//  a2 x + b2 y + c2 + k2 t = 0
//  a3 x + b3 y + c3 + k3 t = 0
//
// or in matrix form
//
//  ( a1 b1 k1 ) ( x )    ( c1 )
//  ( a2 b2 k2 ) ( y ) = -( c2 )          Ax = b
//  ( a3 b3 k3 ) ( t )    ( c3 )
//
//  Cramers rule x_i = det(A_i)/det(A)
//  where A_i is A with column i replaced by b

int solve( Site* s1, double k1,
           Site* s2, double k2,
           Site* s3, double k3, std::vector<Solution>& slns ) {
    if (debug && !silent)
        std::cout << "LLLSolver.\n";

    assert( s1->isLine() && s2->isLine() && s3->isLine() );

    std::vector< Eq<qd_real> > eq; // equation-parameters, in quad-precision
    boost::array<Site*,3> sites = {{s1,s2,s3}};
    boost::array<double,3> kvals = {{k1,k2,k3}};
    for (unsigned int i=0;i<3;i++)
        eq.push_back( sites[i]->eqp_qd( kvals[i] ) );

    unsigned int i = 0, j=1, k=2;
    qd_real d = chop( determinant( eq[i].a, eq[i].b, eq[i].k,
                                            eq[j].a, eq[j].b, eq[j].k,
                                            eq[k].a, eq[k].b, eq[k].k ) );
    double det_eps = 1e-6;
    if ( fabs(d) > det_eps ) {
        qd_real t = determinant(  eq[i].a, eq[i].b, -eq[i].c,
                                  eq[j].a, eq[j].b, -eq[j].c,
                                  eq[k].a, eq[k].b, -eq[k].c ) / d ;
        if (t >= 0) {
            qd_real sol_x = determinant(  -eq[i].c, eq[i].b, eq[i].k,
                                          -eq[j].c, eq[j].b, eq[j].k,
                                          -eq[k].c, eq[k].b, eq[k].k ) / d ;
            qd_real sol_y = determinant(  eq[i].a, -eq[i].c, eq[i].k,
                                          eq[j].a, -eq[j].c, eq[j].k,
                                          eq[k].a, -eq[k].c, eq[k].k ) / d ;
            if (debug && !silent )
                std::cout << " solution: " << Point( to_double(sol_x), to_double(sol_y) ) << " t=" << to_double(t) << " k3=" << k3 << " det=" << to_double(d) << "\n";

            slns.push_back( Solution( Point( to_double(sol_x), to_double(sol_y) ), to_double(t), k3 ) ); // kk3 just passes through without any effect!?
            return 1;
        }
    } else {
        if (debug && !silent) {
            std::cout << "WARNING: LLLSolver small determinant! no solutions. d= " << d <<"\n";
            std::cout << " s1 : " << eq[0].a << " " << eq[0].b << " " << eq[0].c << " " << eq[0].k << "\n";
            std::cout << " s2 : " << eq[1].a << " " << eq[1].b << " " << eq[1].c << " " << eq[1].k << "\n";
            std::cout << " s3 : " << eq[2].a << " " << eq[2].b << " " << eq[2].c << " " << eq[2].k << "\n";
            //std::cout << " 0==1? " << (eq[0]==eq[1]) << "\n";
            //std::cout << "da = " << (eq[0].a-eq[1].a) << "\n";
            //std::cout << "db = " << (eq[0].b-eq[1].b) << "\n";
            //std::cout << "dc = " << (eq[0].c-eq[1].c) << "\n";
        }

    }
    return 0; // no solution if determinant zero, or t-value negative
}

};

} // solvers
} // ovd

<commit_msg>Try parallel solver if determinant of LLL solver is close to zero.<commit_after>/*
 *  Copyright 2010-2011 Anders Wallin (anders.e.e.wallin "at" gmail.com)
 *
 *  Idea and code for point/line/arc voronoi-vertex positioning code by
 *  Andy Payne, andy "at" payne "dot" org, November, 2010
 *  see: http://www.payne.org/index.php/Calculating_Voronoi_Nodes
 *
 *  This file is part of OpenVoronoi.
 *
 *  OpenVoronoi is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  OpenVoronoi is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with OpenVoronoi.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "solvers/solver_lll_para.hpp"

#include "common/point.hpp"
#include "common/numeric.hpp"

using namespace ovd::numeric; // sq() chop() determinant()

namespace ovd {
namespace solvers {

/// \brief line-line-line Solver
///
/// solves 3x3 system.
class LLLSolver : public Solver {
public:

//  a1 x + b1 y + c1 + k1 t = 0
//  a2 x + b2 y + c2 + k2 t = 0
//  a3 x + b3 y + c3 + k3 t = 0
//
// or in matrix form
//
//  ( a1 b1 k1 ) ( x )    ( c1 )
//  ( a2 b2 k2 ) ( y ) = -( c2 )          Ax = b
//  ( a3 b3 k3 ) ( t )    ( c3 )
//
//  Cramers rule x_i = det(A_i)/det(A)
//  where A_i is A with column i replaced by b

int solve( Site* s1, double k1,
           Site* s2, double k2,
           Site* s3, double k3, std::vector<Solution>& slns ) {
    if (debug && !silent)
        std::cout << "LLLSolver.\n";

    assert( s1->isLine() && s2->isLine() && s3->isLine() );

    std::vector< Eq<qd_real> > eq; // equation-parameters, in quad-precision
    boost::array<Site*,3> sites = {{s1,s2,s3}};
    boost::array<double,3> kvals = {{k1,k2,k3}};
    for (unsigned int i=0;i<3;i++)
        eq.push_back( sites[i]->eqp_qd( kvals[i] ) );

    unsigned int i = 0, j=1, k=2;
    qd_real d = chop( determinant( eq[i].a, eq[i].b, eq[i].k,
                                            eq[j].a, eq[j].b, eq[j].k,
                                            eq[k].a, eq[k].b, eq[k].k ) );
    double det_eps = 1e-6;
    if ( fabs(d) > det_eps ) {
        qd_real t = determinant(  eq[i].a, eq[i].b, -eq[i].c,
                                  eq[j].a, eq[j].b, -eq[j].c,
                                  eq[k].a, eq[k].b, -eq[k].c ) / d ;
        if (t >= 0) {
            qd_real sol_x = determinant(  -eq[i].c, eq[i].b, eq[i].k,
                                          -eq[j].c, eq[j].b, eq[j].k,
                                          -eq[k].c, eq[k].b, eq[k].k ) / d ;
            qd_real sol_y = determinant(  eq[i].a, -eq[i].c, eq[i].k,
                                          eq[j].a, -eq[j].c, eq[j].k,
                                          eq[k].a, -eq[k].c, eq[k].k ) / d ;
            if (debug && !silent )
                std::cout << " solution: " << Point( to_double(sol_x), to_double(sol_y) ) << " t=" << to_double(t) << " k3=" << k3 << " det=" << to_double(d) << "\n";

            slns.push_back( Solution( Point( to_double(sol_x), to_double(sol_y) ), to_double(t), k3 ) ); // kk3 just passes through without any effect!?
            return 1;
        }
    } else {
        // Try parallel solver as fallback, if the small determinant is due to nearly parallel edges
        for (i = 0; i < 3; i++)
        {
            j = (i+1)%3;
            double delta = to_double(fabs(eq[i].a*eq[j].b - eq[j].a*eq[i].b));
            if (delta <= 1024.0*std::numeric_limits<double>::epsilon())
            {
                s1 = sites[i];
                k1 = kvals[i];
                s2 = sites[j];
                k2 = kvals[j];
                s3 = sites[(i+2)%3];
                k3 = kvals[(i+2)%3];
                LLLPARASolver para_solver;
                para_solver.set_debug(true);
                para_solver.set_silent(false);
                return para_solver.solve(s1, k1, s2, k2, s3, k3, slns);
            }
        }
        if (debug && !silent) {
            std::cout << "WARNING: LLLSolver small determinant! no solutions. d= " << d <<"\n";
            std::cout << " s1 : " << eq[0].a << " " << eq[0].b << " " << eq[0].c << " " << eq[0].k << "\n";
            std::cout << " s2 : " << eq[1].a << " " << eq[1].b << " " << eq[1].c << " " << eq[1].k << "\n";
            std::cout << " s3 : " << eq[2].a << " " << eq[2].b << " " << eq[2].c << " " << eq[2].k << "\n";
            //std::cout << " 0==1? " << (eq[0]==eq[1]) << "\n";
            //std::cout << "da = " << (eq[0].a-eq[1].a) << "\n";
            //std::cout << "db = " << (eq[0].b-eq[1].b) << "\n";
            //std::cout << "dc = " << (eq[0].c-eq[1].c) << "\n";
        }

    }
    return 0; // no solution if determinant zero, or t-value negative
}

};

} // solvers
} // ovd

<|endoftext|>


<commit_before>/*
 * File:  ft_index_data.cpp
 * Copyright (C) 2004 The Institute for System Programming of the Russian Academy of Sciences (ISP RAS)
 */

#include "common/sedna.h"

#include "tr/ft/ft_index_data.h"
#include "common/xptr.h"
#include "tr/crmutils/node_utils.h"
#include "tr/vmm/vmm.h"
#include "tr/executor/base/tuple.h"
#include "tr/ft/FTindex.h"
#include "tr/log/log.h"
#include "tr/structures/schema.h"
#include "tr/executor/fo/casting_operations.h"
//#include "indexes.h"
#include "tr/executor/base/dm_accessors.h"

using namespace std;

pers_sset<ft_index_cell,unsigned short> *ft_indexdata;
index_id   *ft_idx_counter;
USemaphore ft_index_sem;//SEMAPHOR!!!

static bool ft_index_initialized = false;

//inits metadata library
void ft_index_on_session_begin(pers_sset<ft_index_cell,unsigned short> * _indexdata_, index_id *_idx_counter_)
{
    ft_indexdata = _indexdata_;
    ft_idx_counter = _idx_counter_;
	//SEMAPHOR INIT SECTION
	if (USemaphoreOpen(&ft_index_sem, FT_INDEX_SEMAPHORE_STR, __sys_call_error) != 0)
        throw USER_EXCEPTION2(SE4012, "FT_INDEX_SEMAPHORE_STR");

    ft_index_initialized = true;
}

void ft_index_on_session_end()
{
    if (!ft_index_initialized) return;
	//SEMAPHOR RELEASE SECTION
    if (USemaphoreClose(ft_index_sem, __sys_call_error) != 0)
        throw USER_EXCEPTION2(SE4013, "FT_INDEX_SEMAPHORE_STR");
    ft_index_initialized = false;
}

pers_sset<ft_index_cell,unsigned short>::pers_sset_entry* search_ft_indexdata_cell(const char *index_title)
{
	return ft_indexdata->get(index_title,NULL);
}
ft_custom_cell* ft_custom_cell::init(xml_ns* _ns, const char* _local,ft_index_type _cm,bool persistent)
{
	ft_custom_cell* ftc=(ft_custom_cell*)scm_malloc(sizeof(ft_custom_cell),persistent);
	ftc->ns=_ns;
	if (_local!=NULL)
	{
		char* z=(char*)scm_malloc(strlen(_local)+1,persistent);
		strcpy(z,_local);
		ftc->local=z;
	}
	else
		ftc->local=NULL;
	ftc->cm=_cm;
	return ftc;
}
void ft_index_cell::delete_custom_tree (pers_sset<ft_custom_cell,unsigned short> * custom_tree)
{
	pers_sset<ft_custom_cell,unsigned short>::pers_sset_entry* tmp=custom_tree->rb_minimum(custom_tree->root);
	while (tmp!=NULL)
	{
		//coll->free_metadata(tmp);
		ft_custom_cell* mdc=tmp->obj;
		if (mdc->local)
			scm_free(mdc->local,IS_PH_PTR(mdc));
		scm_free(mdc,IS_PH_PTR(mdc));
		tmp->obj=NULL;
		tmp=custom_tree->rb_successor(tmp);
		RECOVERY_CRASH;
	}
	pers_sset<ft_custom_cell,unsigned short>::sset_free(custom_tree);
}
void inline free_ft_indexdata_cell(pers_sset<ft_index_cell,unsigned short>::pers_sset_entry* entry)
{
	ft_index_cell* idc=entry->obj;
	ft_indexdata->rb_delete(entry);
	if (idc->index_title!=NULL)
		scm_free(idc->index_title,true);
	delete_PathExpr(idc->object);
	scm_free(idc->doc_name,true);
	if (idc->custom_tree!=NULL)
		ft_index_cell::delete_custom_tree(idc->custom_tree);
	scm_free(idc,true);
}
bool ft_index_cell::fits_to_index(schema_node* snode)
{
	t_scmnodes res;
	t_scmnodes objs=execute_abs_path_expr(snode->root,object);
	t_scmnodes::iterator it=objs.begin();
	while (it!=objs.end())
	{
		if (*it==snode)
			return true;
		it++;
	}
	return false;
}
ft_index_cell* ft_index_cell::create_index (PathExpr *object_path, ft_index_type it, doc_schema_node* schemaroot,const char * index_title, const char* doc_name,bool is_doc,std::vector< std::pair< std::pair<xml_ns*,char*>,ft_index_type> >* templ, bool just_heap)
{
	// I. Create and fill new index cell
	ft_index_sem_down();
	if (search_ft_indexdata_cell(index_title)!=NULL)
	{
		ft_index_sem_up();
		throw USER_EXCEPTION(SE2033);
	}
	down_concurrent_micro_ops_number();
	ft_index_cell* idc=(ft_index_cell*)scm_malloc(sizeof(ft_index_cell),true);
    idc->id = *ft_idx_counter;
    (*ft_idx_counter)++;
	idc->schemaroot = schemaroot;
	schemaroot->create_ft_index(idc);
	idc->object = object_path;
	idc->ftype=it;
	idc->index_title=(char*)scm_malloc(strlen(index_title)+1,true);
	strcpy(idc->index_title,index_title);
	idc->doc_name=(char*)scm_malloc(strlen(doc_name)+1,true);
	strcpy(idc->doc_name,doc_name);
	idc->is_doc=is_doc;
	if (it==ft_customized_value && templ!=NULL)
	{
		idc->custom_tree= pers_sset<ft_custom_cell,unsigned short>::init();
		std::vector<std::pair<std::pair<xml_ns*,char*>,ft_index_type> >::iterator tmp=templ->begin();
		while (tmp!=templ->end())
		{

			idc->custom_tree->put(ft_custom_cell::init((*tmp).first.first,(*tmp).first.second,(*tmp).second));
			tmp++;
		}
	}
	/*idc->next = *indexdata;
	if ((*indexdata) != NULL) (*indexdata)->pred = idc;
	*indexdata = idc;*/
	ft_indexdata->put(idc);
	ft_index_sem_up();
    hl_logical_log_ft_index(object_path, it,(char *) index_title, doc_name,is_doc,idc->custom_tree,true);
	up_concurrent_micro_ops_number();
	// ALGORITHM: indexing data
	//II. Execute abs path (object_path) on the desriptive schema
	if (!just_heap)
	{
		t_scmnodes sobj = execute_abs_path_expr(schemaroot, object_path);
		//III. For each schema node found (sn_obj)
		std::vector<xptr> start_nodes;
		for (int i = 0; i < sobj.size(); i++)
		{
			xptr blk= sobj[i]->bblk;
			sobj[i]->add_ft_index(idc);
			RECOVERY_CRASH;
			if (blk!=XNULL)
			{
			CHECKP(blk);
			start_nodes.push_back((GETBLOCKFIRSTDESCRIPTORABSOLUTE(((node_blk_hdr*)XADDR(blk)))));
			}
		}

		SednaIndexJob sij(idc);
		sij.create_index(&start_nodes);
	}
	return idc;
}
void ft_index_cell::delete_index (const char *index_title, bool just_heap)
{
	ft_index_sem_down();
	pers_sset<ft_index_cell,unsigned short>::pers_sset_entry* idc=search_ft_indexdata_cell(index_title);
	if (idc!=NULL)
	{

		down_concurrent_micro_ops_number();
		hl_logical_log_ft_index((idc->obj)->object,(idc->obj)->ftype,(idc->obj)->index_title,(idc->obj)->doc_name,(idc->obj)->is_doc,(idc->obj)->custom_tree,false);
		if (!just_heap) //FIXME: mb move out of down_concurrent_micro_ops_number() block
		{
			SednaIndexJob sij(idc->obj);
			sij.clear_index();
		}
		ft_index_cell* ic=idc->obj;
		doc_schema_node* sm=(idc->obj)->schemaroot;
		free_ft_indexdata_cell(idc);
		RECOVERY_CRASH;
		(*ft_idx_counter)--;
		sm->delete_ft_index(ic);
		ft_index_sem_up();
		up_concurrent_micro_ops_number();
	}
	else
		ft_index_sem_up();
}
ft_index_cell* ft_index_cell::find_index(const char* title)
{
	xptr res;
    ft_index_sem_down();
	pers_sset<ft_index_cell,unsigned short>::pers_sset_entry* idc=search_ft_indexdata_cell(title);
	if (idc==NULL)
	{
		ft_index_sem_up();
		return NULL;
	}
	else
	{
		ft_index_sem_up();
		return idc->obj;
	}
}
void ft_index_cell::update_index(xptr_sequence* upserted)
{
	SednaIndexJob sij(this);
	sij.update_index(upserted);

}
void ft_index_cell::insert_to_index(xptr_sequence* upserted)
{
	SednaIndexJob sij(this);
	sij.insert_into_index(upserted);

}
void ft_index_cell::delete_from_index(xptr_sequence* deleted)
{
	SednaIndexJob sij(this);
	sij.delete_from_index(deleted);
}
void ft_index_cell::change_index(xptr_sequence* inserted,xptr_sequence* updated,xptr_sequence* deleted)
{
	SednaIndexJob sij(this);
	sij.insert_into_index(inserted);
	sij.update_index(updated);
	sij.delete_from_index(deleted);
}
<commit_msg>ft index on create rcv fix<commit_after>/*
 * File:  ft_index_data.cpp
 * Copyright (C) 2004 The Institute for System Programming of the Russian Academy of Sciences (ISP RAS)
 */

#include "common/sedna.h"

#include "tr/ft/ft_index_data.h"
#include "common/xptr.h"
#include "tr/crmutils/node_utils.h"
#include "tr/vmm/vmm.h"
#include "tr/executor/base/tuple.h"
#include "tr/ft/FTindex.h"
#include "tr/log/log.h"
#include "tr/structures/schema.h"
#include "tr/executor/fo/casting_operations.h"
//#include "indexes.h"
#include "tr/executor/base/dm_accessors.h"

using namespace std;

pers_sset<ft_index_cell,unsigned short> *ft_indexdata;
index_id   *ft_idx_counter;
USemaphore ft_index_sem;//SEMAPHOR!!!

static bool ft_index_initialized = false;

//inits metadata library
void ft_index_on_session_begin(pers_sset<ft_index_cell,unsigned short> * _indexdata_, index_id *_idx_counter_)
{
    ft_indexdata = _indexdata_;
    ft_idx_counter = _idx_counter_;
	//SEMAPHOR INIT SECTION
	if (USemaphoreOpen(&ft_index_sem, FT_INDEX_SEMAPHORE_STR, __sys_call_error) != 0)
        throw USER_EXCEPTION2(SE4012, "FT_INDEX_SEMAPHORE_STR");

    ft_index_initialized = true;
}

void ft_index_on_session_end()
{
    if (!ft_index_initialized) return;
	//SEMAPHOR RELEASE SECTION
    if (USemaphoreClose(ft_index_sem, __sys_call_error) != 0)
        throw USER_EXCEPTION2(SE4013, "FT_INDEX_SEMAPHORE_STR");
    ft_index_initialized = false;
}

pers_sset<ft_index_cell,unsigned short>::pers_sset_entry* search_ft_indexdata_cell(const char *index_title)
{
	return ft_indexdata->get(index_title,NULL);
}
ft_custom_cell* ft_custom_cell::init(xml_ns* _ns, const char* _local,ft_index_type _cm,bool persistent)
{
	ft_custom_cell* ftc=(ft_custom_cell*)scm_malloc(sizeof(ft_custom_cell),persistent);
	ftc->ns=_ns;
	if (_local!=NULL)
	{
		char* z=(char*)scm_malloc(strlen(_local)+1,persistent);
		strcpy(z,_local);
		ftc->local=z;
	}
	else
		ftc->local=NULL;
	ftc->cm=_cm;
	return ftc;
}
void ft_index_cell::delete_custom_tree (pers_sset<ft_custom_cell,unsigned short> * custom_tree)
{
	pers_sset<ft_custom_cell,unsigned short>::pers_sset_entry* tmp=custom_tree->rb_minimum(custom_tree->root);
	while (tmp!=NULL)
	{
		//coll->free_metadata(tmp);
		ft_custom_cell* mdc=tmp->obj;
		if (mdc->local)
			scm_free(mdc->local,IS_PH_PTR(mdc));
		scm_free(mdc,IS_PH_PTR(mdc));
		tmp->obj=NULL;
		tmp=custom_tree->rb_successor(tmp);
		RECOVERY_CRASH;
	}
	pers_sset<ft_custom_cell,unsigned short>::sset_free(custom_tree);
}
void inline free_ft_indexdata_cell(pers_sset<ft_index_cell,unsigned short>::pers_sset_entry* entry)
{
	ft_index_cell* idc=entry->obj;
	ft_indexdata->rb_delete(entry);
	if (idc->index_title!=NULL)
		scm_free(idc->index_title,true);
	delete_PathExpr(idc->object);
	scm_free(idc->doc_name,true);
	if (idc->custom_tree!=NULL)
		ft_index_cell::delete_custom_tree(idc->custom_tree);
	scm_free(idc,true);
}
bool ft_index_cell::fits_to_index(schema_node* snode)
{
	t_scmnodes res;
	t_scmnodes objs=execute_abs_path_expr(snode->root,object);
	t_scmnodes::iterator it=objs.begin();
	while (it!=objs.end())
	{
		if (*it==snode)
			return true;
		it++;
	}
	return false;
}
ft_index_cell* ft_index_cell::create_index (PathExpr *object_path, ft_index_type it, doc_schema_node* schemaroot,const char * index_title, const char* doc_name,bool is_doc,std::vector< std::pair< std::pair<xml_ns*,char*>,ft_index_type> >* templ, bool just_heap)
{
	// I. Create and fill new index cell
	ft_index_sem_down();
	if (search_ft_indexdata_cell(index_title)!=NULL)
	{
		ft_index_sem_up();
		throw USER_EXCEPTION(SE2033);
	}
	down_concurrent_micro_ops_number();
	ft_index_cell* idc=(ft_index_cell*)scm_malloc(sizeof(ft_index_cell),true);
    idc->id = *ft_idx_counter;
    (*ft_idx_counter)++;
	idc->schemaroot = schemaroot;
	schemaroot->create_ft_index(idc);
	idc->object = object_path;
	idc->ftype=it;
	idc->index_title=(char*)scm_malloc(strlen(index_title)+1,true);
	strcpy(idc->index_title,index_title);
	idc->doc_name=(char*)scm_malloc(strlen(doc_name)+1,true);
	strcpy(idc->doc_name,doc_name);
	idc->is_doc=is_doc;
	if (it==ft_customized_value && templ!=NULL)
	{
		idc->custom_tree= pers_sset<ft_custom_cell,unsigned short>::init();
		std::vector<std::pair<std::pair<xml_ns*,char*>,ft_index_type> >::iterator tmp=templ->begin();
		while (tmp!=templ->end())
		{

			idc->custom_tree->put(ft_custom_cell::init((*tmp).first.first,(*tmp).first.second,(*tmp).second));
			tmp++;
		}
	}
	/*idc->next = *indexdata;
	if ((*indexdata) != NULL) (*indexdata)->pred = idc;
	*indexdata = idc;*/
	ft_indexdata->put(idc);
	ft_index_sem_up();
    hl_logical_log_ft_index(object_path, it,(char *) index_title, doc_name,is_doc,idc->custom_tree,true);

	if (just_heap) up_concurrent_micro_ops_number(); // because here we don't modify ph

	// ALGORITHM: indexing data
	//II. Execute abs path (object_path) on the desriptive schema
	if (!just_heap)
	{
		t_scmnodes sobj = execute_abs_path_expr(schemaroot, object_path);
		//III. For each schema node found (sn_obj)
		std::vector<xptr> start_nodes;
		for (int i = 0; i < sobj.size(); i++)
		{
			xptr blk= sobj[i]->bblk;
			sobj[i]->add_ft_index(idc);
			RECOVERY_CRASH;
			if (blk!=XNULL)
			{
			CHECKP(blk);
			start_nodes.push_back((GETBLOCKFIRSTDESCRIPTORABSOLUTE(((node_blk_hdr*)XADDR(blk)))));
			}
		}

		up_concurrent_micro_ops_number(); // added because we shoudn't modify ph outside of micro-op

		// ft_index recovery should take the responsibility here
		SednaIndexJob sij(idc);
		sij.create_index(&start_nodes);
	}
	return idc;
}
void ft_index_cell::delete_index (const char *index_title, bool just_heap)
{
	ft_index_sem_down();
	pers_sset<ft_index_cell,unsigned short>::pers_sset_entry* idc=search_ft_indexdata_cell(index_title);
	if (idc!=NULL)
	{

		down_concurrent_micro_ops_number();
		hl_logical_log_ft_index((idc->obj)->object,(idc->obj)->ftype,(idc->obj)->index_title,(idc->obj)->doc_name,(idc->obj)->is_doc,(idc->obj)->custom_tree,false);
		if (!just_heap) //FIXME: mb move out of down_concurrent_micro_ops_number() block
		{
			SednaIndexJob sij(idc->obj);
			sij.clear_index();
		}
		ft_index_cell* ic=idc->obj;
		doc_schema_node* sm=(idc->obj)->schemaroot;
		free_ft_indexdata_cell(idc);
		RECOVERY_CRASH;
		(*ft_idx_counter)--;
		sm->delete_ft_index(ic);
		ft_index_sem_up();
		up_concurrent_micro_ops_number();
	}
	else
		ft_index_sem_up();
}
ft_index_cell* ft_index_cell::find_index(const char* title)
{
	xptr res;
    ft_index_sem_down();
	pers_sset<ft_index_cell,unsigned short>::pers_sset_entry* idc=search_ft_indexdata_cell(title);
	if (idc==NULL)
	{
		ft_index_sem_up();
		return NULL;
	}
	else
	{
		ft_index_sem_up();
		return idc->obj;
	}
}
void ft_index_cell::update_index(xptr_sequence* upserted)
{
	SednaIndexJob sij(this);
	sij.update_index(upserted);

}
void ft_index_cell::insert_to_index(xptr_sequence* upserted)
{
	SednaIndexJob sij(this);
	sij.insert_into_index(upserted);

}
void ft_index_cell::delete_from_index(xptr_sequence* deleted)
{
	SednaIndexJob sij(this);
	sij.delete_from_index(deleted);
}
void ft_index_cell::change_index(xptr_sequence* inserted,xptr_sequence* updated,xptr_sequence* deleted)
{
	SednaIndexJob sij(this);
	sij.insert_into_index(inserted);
	sij.update_index(updated);
	sij.delete_from_index(deleted);
}
<|endoftext|>