<commit_before>/*
 This file is part of SWGANH. For more information, visit http://swganh.com

 Copyright (c) 2006 - 2011 The SWG:ANH Team

 This program 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 2
 of the License, or (at your option) any later version.

 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include <exception>
#include <iostream>
#include <string>

#include <boost/thread.hpp>

#include "anh/logger.h"

#include "swganh/app/swganh_app.h"
#include "swganh/scripting/utilities.h"

#include "version.h"

using namespace boost;
using namespace swganh;
using namespace std;

int main(int argc, char* argv[])
{
    Py_Initialize();
	PyEval_InitThreads();

    // Step 2: Release the GIL from the main thread so that other threads can use it
    PyEval_ReleaseThread(PyGILState_GetThisThreadState());

    try {
        app::SwganhApp app;

        app.Initialize(argc, argv);

        app.Start();

        for (;;) {
            string cmd;
            cin >> cmd;

            if (cmd.compare("exit") == 0 || cmd.compare("quit") == 0 || cmd.compare("q") == 0) {
                LOG(info) << "Exit command received from command line. Shutting down.";

                // Stop the application and join the thread until it's finished.
                app.Stop();

                break;
            } else if(cmd.compare("console") == 0) {
                anh::Logger::getInstance().DisableConsoleLogging();

                std::system("cls");
                std::cout << "swgpy console " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_PATCH << std::endl;

                swganh::scripting::ScopedGilLock lock;
                PyRun_InteractiveLoop(stdin, "<stdin>");

                anh::Logger::getInstance().EnableConsoleLogging();
            } else {
                LOG(warning) << "Invalid command received: " << cmd;
                std::cout << "Type exit or (q)uit to quit" << std::endl;
            }
        }

    } catch(std::exception& e) {
        LOG(fatal) << "Unhandled application exception occurred: " << e.what();
    }

    // Step 4: Lock the GIL before calling finalize
    PyGILState_Ensure();
    Py_Finalize();

    return 0;
}
<commit_msg>Add the kernel to the dictionary<commit_after>/*
 This file is part of SWGANH. For more information, visit http://swganh.com

 Copyright (c) 2006 - 2011 The SWG:ANH Team

 This program 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 2
 of the License, or (at your option) any later version.

 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include <exception>
#include <iostream>
#include <string>

#include <boost/thread.hpp>
#include <boost/python.hpp>

#include "anh/logger.h"

#include "swganh/app/swganh_app.h"
#include "swganh/scripting/utilities.h"

#include "version.h"

using namespace boost;
using namespace swganh;
using namespace std;

int main(int argc, char* argv[])
{
    Py_Initialize();
	PyEval_InitThreads();

    // Step 2: Release the GIL from the main thread so that other threads can use it
    PyEval_ReleaseThread(PyGILState_GetThisThreadState());

    try {
        app::SwganhApp app;

        app.Initialize(argc, argv);

        app.Start();

        for (;;) {
            string cmd;
            cin >> cmd;

            if (cmd.compare("exit") == 0 || cmd.compare("quit") == 0 || cmd.compare("q") == 0) {
                LOG(info) << "Exit command received from command line. Shutting down.";

                // Stop the application and join the thread until it's finished.
                app.Stop();

                break;
            } else if(cmd.compare("console") == 0) {
                swganh::scripting::ScopedGilLock lock;
                anh::Logger::getInstance().DisableConsoleLogging();

                std::system("cls");
                std::cout << "swgpy console " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_PATCH << std::endl;

                boost::python::object main = boost::python::object (boost::python::handle<>(boost::python::borrowed(
                    PyImport_AddModule("__main__")
                )));
                auto global_dict = main.attr("__dict__");
                global_dict["kernel"] = boost::python::ptr(app.GetAppKernel());

                PyRun_InteractiveLoop(stdin, "<stdin>");

                anh::Logger::getInstance().EnableConsoleLogging();
            } else {
                LOG(warning) << "Invalid command received: " << cmd;
                std::cout << "Type exit or (q)uit to quit" << std::endl;
            }
        }

    } catch(std::exception& e) {
        LOG(fatal) << "Unhandled application exception occurred: " << e.what();
    }

    // Step 4: Lock the GIL before calling finalize
    PyGILState_Ensure();
    Py_Finalize();

    return 0;
}
<|endoftext|>


<commit_before>#include "storage.hpp"

#include "../base/logging.hpp"
#include "../base/string_utils.hpp"

#include "../indexer/data_header.hpp"

#include "../coding/file_writer.hpp"
#include "../coding/file_reader.hpp"
#include "../coding/file_container.hpp"
#include "../coding/strutil.hpp"

#include "../version/version.hpp"

#include "../std/set.hpp"
#include "../std/algorithm.hpp"
#include "../std/target_os.hpp"

#include <boost/bind.hpp>

#include "../base/start_mem_debug.hpp"

namespace storage
{
  const int TIndex::INVALID = -1;

  static string ErrorString(DownloadResult res)
  {
    switch (res)
    {
    case EHttpDownloadCantCreateFile:
      return "File can't be created. Probably, you have no disk space available or "
                         "using read-only file system.";
    case EHttpDownloadFailed:
      return "Download failed due to missing or poor connection. "
                         "Please, try again later.";
    case EHttpDownloadFileIsLocked:
      return "Download can't be finished because file is locked. "
                         "Please, try again after restarting application.";
    case EHttpDownloadFileNotFound:
      return "Requested file is absent on the server.";
    case EHttpDownloadNoConnectionAvailable:
      return "No network connection is available.";
    case EHttpDownloadOk:
      return "Download finished successfully.";
    }
    return "Unknown error";
  }

  ////////////////////////////////////////////////////////////////////////////
  void Storage::Init(TAddMapFunction addFunc, TRemoveMapFunction removeFunc, TUpdateRectFunction updateRectFunc)
  {
    m_currentVersion = static_cast<uint32_t>(Version::BUILD);

    m_addMap = addFunc;
    m_removeMap = removeFunc;
    m_updateRect = updateRectFunc;

    // activate all downloaded maps
    Platform & p = GetPlatform();
    Platform::FilesList filesList;
    string const dataPath = p.WritableDir();
    p.GetFilesInDir(dataPath, "*" DATA_FILE_EXTENSION, filesList);
    for (Platform::FilesList::iterator it = filesList.begin(); it != filesList.end(); ++it)
    { // simple way to avoid continuous crashes with invalid data files
      try {
        m_addMap(dataPath + *it);
      } catch (std::exception const & e)
      {
        FileWriter::DeleteFileX(dataPath + *it);
        LOG(LWARNING, (e.what(), "while adding file", *it, "so this file is deleted"));
      }
    }
  }

  string Storage::UpdateBaseUrl() const
  {
    return UPDATE_BASE_URL OMIM_OS_NAME "/" + utils::to_string(m_currentVersion) + "/";
  }

  TCountriesContainer const & NodeFromIndex(TCountriesContainer const & root, TIndex const & index)
  {
    // complex logic to avoid [] out_of_bounds exceptions
    if (index.m_group == TIndex::INVALID || index.m_group >= static_cast<int>(root.SiblingsCount()))
      return root;
    else
    {
      if (index.m_country == TIndex::INVALID || index.m_country >= static_cast<int>(root[index.m_group].SiblingsCount()))
        return root[index.m_group];
      if (index.m_region == TIndex::INVALID || index.m_region >= static_cast<int>(root[index.m_group][index.m_country].SiblingsCount()))
        return root[index.m_group][index.m_country];
      return root[index.m_group][index.m_country][index.m_region];
    }
  }

  Country const & Storage::CountryByIndex(TIndex const & index) const
  {
    return NodeFromIndex(m_countries, index).Value();
  }

  size_t Storage::CountriesCount(TIndex const & index) const
  {
    return NodeFromIndex(m_countries, index).SiblingsCount();
  }

  string Storage::CountryName(TIndex const & index) const
  {
    return NodeFromIndex(m_countries, index).Value().Name();
  }

  TLocalAndRemoteSize Storage::CountrySizeInBytes(TIndex const & index) const
  {
    return CountryByIndex(index).Size();
  }

  TStatus Storage::CountryStatus(TIndex const & index) const
  {
    // first, check if we already downloading this country or have in in the queue
    TQueue::const_iterator found = std::find(m_queue.begin(), m_queue.end(), index);
    if (found != m_queue.end())
    {
      if (found == m_queue.begin())
        return EDownloading;
      else
        return EInQueue;
    }

    // second, check if this country has failed while downloading
    if (m_failedCountries.find(index) != m_failedCountries.end())
      return EDownloadFailed;

    TLocalAndRemoteSize size = CountryByIndex(index).Size();
    if (size.first == size.second)
    {
      if (size.second == 0)
        return EUnknown;
      else
        return EOnDisk;
    }

    return ENotDownloaded;
  }

  void Storage::DownloadCountry(TIndex const & index)
  {
    // check if we already downloading this country
    TQueue::const_iterator found = find(m_queue.begin(), m_queue.end(), index);
    if (found != m_queue.end())
    { // do nothing
      return;
    }
    // remove it from failed list
    m_failedCountries.erase(index);
    // add it into the queue
    m_queue.push_back(index);
    // and start download if necessary
    if (m_queue.size() == 1)
    {
      // reset total country's download progress
      TLocalAndRemoteSize size = CountryByIndex(index).Size();
      m_countryProgress = TDownloadProgress(0, size.second);

      DownloadNextCountryFromQueue();
    }
    else
    { // notify about "In Queue" status
      if (m_observerChange)
        m_observerChange(index);
    }
  }

  template <class TRemoveFn>
  class DeactivateMap
  {
    string m_workingDir;
    TRemoveFn & m_removeFn;
  public:
    DeactivateMap(TRemoveFn & removeFn) : m_removeFn(removeFn)
    {
      m_workingDir = GetPlatform().WritableDir();
    }
    void operator()(TTile const & tile)
    {
      string const file = m_workingDir + tile.first;
      m_removeFn(file);
    }
  };

  void Storage::DownloadNextCountryFromQueue()
  {
    while (!m_queue.empty())
    {
      TIndex index = m_queue.front();
      TTilesContainer const & tiles = CountryByIndex(index).Tiles();
      for (TTilesContainer::const_iterator it = tiles.begin(); it != tiles.end(); ++it)
      {
        if (!IsTileDownloaded(*it))
        {
          GetDownloadManager().DownloadFile(
              (UpdateBaseUrl() + UrlEncode(it->first)).c_str(),
              (GetPlatform().WritablePathForFile(it->first).c_str()),
              bind(&Storage::OnMapDownloadFinished, this, _1, _2),
              bind(&Storage::OnMapDownloadProgress, this, _1, _2),
              true);  // enabled resume support by default
          // notify GUI - new status for country, "Downloading"
          if (m_observerChange)
            m_observerChange(index);
          return;
        }
      }
      // continue with next country
      m_queue.pop_front();
      // reset total country's download progress
      if (!m_queue.empty())
        m_countryProgress = TDownloadProgress(0, CountryByIndex(m_queue.front()).Size().second);
      // and notify GUI - new status for country, "OnDisk"
      if (m_observerChange)
        m_observerChange(index);
    }
  }

  struct CancelDownloading
  {
    string const m_baseUrl;
    CancelDownloading(string const & baseUrl) : m_baseUrl(baseUrl) {}
    void operator()(TTile const & tile)
    {
      GetDownloadManager().CancelDownload((m_baseUrl + UrlEncode(tile.first)).c_str());
    }
  };

  class DeleteMap
  {
    string m_workingDir;
  public:
    DeleteMap()
    {
		  m_workingDir = GetPlatform().WritableDir();
    }
    /// @TODO do not delete other countries cells
    void operator()(TTile const & tile)
    {
      FileWriter::DeleteFileX(m_workingDir + tile.first);
    }
  };

  template <typename TRemoveFunc>
  void DeactivateAndDeleteCountry(Country const & country, TRemoveFunc removeFunc)
  {
    // deactivate from multiindex
    for_each(country.Tiles().begin(), country.Tiles().end(), DeactivateMap<TRemoveFunc>(removeFunc));
    // delete from disk
    for_each(country.Tiles().begin(), country.Tiles().end(), DeleteMap());
  }

  void Storage::DeleteCountry(TIndex const & index)
  {
    Country const & country = CountryByIndex(index);

    m2::RectD bounds;

    // check if we already downloading this country
    TQueue::iterator found = find(m_queue.begin(), m_queue.end(), index);
    if (found != m_queue.end())
    {
      if (found == m_queue.begin())
      { // stop download
        for_each(country.Tiles().begin(), country.Tiles().end(), CancelDownloading(UpdateBaseUrl()));
        // remove from the queue
        m_queue.erase(found);
        // start another download if the queue is not empty
        DownloadNextCountryFromQueue();
      }
      else
      { // remove from the queue
        m_queue.erase(found);
      }
    }
    else
    {
      // bounds are only updated if country was already activated before
      bounds = country.Bounds();
    }

    DeactivateAndDeleteCountry(country, m_removeMap);
    if (m_observerChange)
      m_observerChange(index);

    if (bounds != m2::RectD::GetEmptyRect())
      m_updateRect(bounds);
  }

  void Storage::ReInitCountries(bool forceReload)
  {
    if (forceReload)
      m_countries.Clear();

    if (m_countries.SiblingsCount() == 0)
    {
      TTilesContainer tiles;
      if (LoadTiles(tiles, GetPlatform().ReadPathForFile(DATA_UPDATE_FILE), m_currentVersion))
      {
        if (!LoadCountries(GetPlatform().ReadPathForFile(COUNTRIES_FILE), tiles, m_countries))
        {
          LOG(LWARNING, ("Can't load countries file", COUNTRIES_FILE));
        }
      }
      else
      {
        LOG(LWARNING, ("Can't load update file", DATA_UPDATE_FILE));
      }
    }
  }

  void Storage::Subscribe(TObserverChangeCountryFunction change, TObserverProgressFunction progress,
                          TUpdateRequestFunction updateRequest)
  {
    m_observerChange = change;
    m_observerProgress = progress;
    m_observerUpdateRequest = updateRequest;

    ReInitCountries(false);
  }

  void Storage::Unsubscribe()
  {
    m_observerChange.clear();
    m_observerProgress.clear();
    m_observerUpdateRequest.clear();
  }

  string FileFromUrl(string const & url)
  {
    return UrlDecode(url.substr(url.find_last_of('/') + 1, string::npos));
  }

  void Storage::OnMapDownloadFinished(char const * url, DownloadResult result)
  {
    if (m_queue.empty())
    {
      ASSERT(false, ("Invalid url?", url));
      return;
    }

    if (result != EHttpDownloadOk)
    {
      // remove failed country from the queue
      TIndex failedIndex = m_queue.front();
      m_queue.pop_front();
      m_failedCountries.insert(failedIndex);
      // notify GUI about failed country
      if (m_observerChange)
        m_observerChange(failedIndex);
    }
    else
    {
      TLocalAndRemoteSize size = CountryByIndex(m_queue.front()).Size();
      if (size.second != 0)
        m_countryProgress.first = size.first;
      // activate downloaded map piece
      string const datFile = GetPlatform().ReadPathForFile(FileFromUrl(url));
      m_addMap(datFile);

      feature::DataHeader header;
      header.Load(FilesContainerR(datFile).GetReader(HEADER_FILE_TAG));
      m_updateRect(header.GetBounds());
    }
    DownloadNextCountryFromQueue();
  }

  void Storage::OnMapDownloadProgress(char const * /*url*/, TDownloadProgress progress)
  {
    if (m_queue.empty())
    {
      ASSERT(false, ("queue can't be empty"));
      return;
    }

    if (m_observerProgress)
      m_observerProgress(m_queue.front(),
          TDownloadProgress(m_countryProgress.first + progress.first, m_countryProgress.second));
  }

  void Storage::CheckForUpdate()
  {
    // at this moment we support only binary update checks
    string const update = UpdateBaseUrl() + BINARY_UPDATE_FILE/*DATA_UPDATE_FILE*/;
    GetDownloadManager().CancelDownload(update.c_str());
    GetDownloadManager().DownloadFile(
        update.c_str(),
        (GetPlatform().WritablePathForFile(DATA_UPDATE_FILE)).c_str(),
        bind(&Storage::OnBinaryUpdateCheckFinished, this, _1, _2),
        TDownloadProgressFunction(), false);
  }

  void Storage::OnDataUpdateCheckFinished(char const * url, DownloadResult result)
  {
    if (result != EHttpDownloadOk)
    {
      LOG(LWARNING, ("Update check failed for url:", url));
      if (m_observerUpdateRequest)
        m_observerUpdateRequest(EDataCheckFailed, ErrorString(result));
    }
    else
    { // @TODO parse update file and notify GUI
    }

    // parse update file
//    TCountriesContainer tempCountries;
//    if (!LoadCountries(tempCountries, GetPlatform().WritablePathForFile(DATA_UPDATE_FILE)))
//    {
//      LOG(LWARNING, ("New application version should be downloaded, "
//                     "update file format can't be parsed"));
//      // @TODO: report to GUI
//      return;
//    }
//    // stop any active download, clear the queue, replace countries and notify GUI
//    if (!m_queue.empty())
//    {
//      CancelCountryDownload(CountryByIndex(m_queue.front()));
//      m_queue.clear();
//    }
//    m_countries.swap(tempCountries);
//    // @TODO report to GUI about reloading all countries
//    LOG(LINFO, ("Update check complete"));
  }

  void Storage::OnBinaryUpdateCheckFinished(char const * url, DownloadResult result)
  {
    if (result == EHttpDownloadFileNotFound)
    { // no binary update is available
      if (m_observerUpdateRequest)
        m_observerUpdateRequest(ENoAnyUpdateAvailable, "No update is available");
    }
    else if (result == EHttpDownloadOk)
    { // update is available!
      try
      {
        if (m_observerUpdateRequest)
        {
          string const updateTextFilePath = GetPlatform().ReadPathForFile(FileFromUrl(url));
          FileReader file(updateTextFilePath);
          m_observerUpdateRequest(ENewBinaryAvailable, file.ReadAsText());
        }
      }
      catch (std::exception const & e)
      {
        if (m_observerUpdateRequest)
          m_observerUpdateRequest(EBinaryCheckFailed,
                                    string("Error loading b-update text file ") + e.what());
      }
    }
    else
    { // connection error
      if (m_observerUpdateRequest)
        m_observerUpdateRequest(EBinaryCheckFailed, ErrorString(result));
    }
  }
}
<commit_msg>Fixed World activation from resources<commit_after>#include "storage.hpp"

#include "../base/logging.hpp"
#include "../base/string_utils.hpp"

#include "../indexer/data_header.hpp"

#include "../coding/file_writer.hpp"
#include "../coding/file_reader.hpp"
#include "../coding/file_container.hpp"
#include "../coding/strutil.hpp"

#include "../version/version.hpp"

#include "../std/set.hpp"
#include "../std/algorithm.hpp"
#include "../std/target_os.hpp"

#include <boost/bind.hpp>

#include "../base/start_mem_debug.hpp"

namespace storage
{
  const int TIndex::INVALID = -1;

  static string ErrorString(DownloadResult res)
  {
    switch (res)
    {
    case EHttpDownloadCantCreateFile:
      return "File can't be created. Probably, you have no disk space available or "
                         "using read-only file system.";
    case EHttpDownloadFailed:
      return "Download failed due to missing or poor connection. "
                         "Please, try again later.";
    case EHttpDownloadFileIsLocked:
      return "Download can't be finished because file is locked. "
                         "Please, try again after restarting application.";
    case EHttpDownloadFileNotFound:
      return "Requested file is absent on the server.";
    case EHttpDownloadNoConnectionAvailable:
      return "No network connection is available.";
    case EHttpDownloadOk:
      return "Download finished successfully.";
    }
    return "Unknown error";
  }

  ////////////////////////////////////////////////////////////////////////////
  void Storage::Init(TAddMapFunction addFunc, TRemoveMapFunction removeFunc, TUpdateRectFunction updateRectFunc)
  {
    m_currentVersion = static_cast<uint32_t>(Version::BUILD);

    m_addMap = addFunc;
    m_removeMap = removeFunc;
    m_updateRect = updateRectFunc;

    // activate all downloaded maps
    Platform & p = GetPlatform();
    Platform::FilesList filesList;
    string const dataPath = p.WritableDir();
    p.GetFilesInDir(dataPath, "*" DATA_FILE_EXTENSION, filesList);
    for (Platform::FilesList::iterator it = filesList.begin(); it != filesList.end(); ++it)
    { // simple way to avoid continuous crashes with invalid data files
      try {
        m_addMap(dataPath + *it);
      } catch (std::exception const & e)
      {
        FileWriter::DeleteFileX(dataPath + *it);
        LOG(LWARNING, (e.what(), "while adding file", *it, "so this file is deleted"));
      }
    }
    // separate code to activate world data file from resources
    // if it's not found in writable data dir
    Platform::FilesList::iterator found = std::find(filesList.begin(), filesList.end(),
                                                    string(WORLD_FILE_NAME DATA_FILE_EXTENSION));
    if (found == filesList.end())
    {
      try {
        m_addMap(p.ReadPathForFile(WORLD_FILE_NAME DATA_FILE_EXTENSION));
      } catch (std::exception const & e)
      {
        LOG(LWARNING, (e.what(), "while adding world data file"));
      }
    }
  }

  string Storage::UpdateBaseUrl() const
  {
    return UPDATE_BASE_URL OMIM_OS_NAME "/" + utils::to_string(m_currentVersion) + "/";
  }

  TCountriesContainer const & NodeFromIndex(TCountriesContainer const & root, TIndex const & index)
  {
    // complex logic to avoid [] out_of_bounds exceptions
    if (index.m_group == TIndex::INVALID || index.m_group >= static_cast<int>(root.SiblingsCount()))
      return root;
    else
    {
      if (index.m_country == TIndex::INVALID || index.m_country >= static_cast<int>(root[index.m_group].SiblingsCount()))
        return root[index.m_group];
      if (index.m_region == TIndex::INVALID || index.m_region >= static_cast<int>(root[index.m_group][index.m_country].SiblingsCount()))
        return root[index.m_group][index.m_country];
      return root[index.m_group][index.m_country][index.m_region];
    }
  }

  Country const & Storage::CountryByIndex(TIndex const & index) const
  {
    return NodeFromIndex(m_countries, index).Value();
  }

  size_t Storage::CountriesCount(TIndex const & index) const
  {
    return NodeFromIndex(m_countries, index).SiblingsCount();
  }

  string Storage::CountryName(TIndex const & index) const
  {
    return NodeFromIndex(m_countries, index).Value().Name();
  }

  TLocalAndRemoteSize Storage::CountrySizeInBytes(TIndex const & index) const
  {
    return CountryByIndex(index).Size();
  }

  TStatus Storage::CountryStatus(TIndex const & index) const
  {
    // first, check if we already downloading this country or have in in the queue
    TQueue::const_iterator found = std::find(m_queue.begin(), m_queue.end(), index);
    if (found != m_queue.end())
    {
      if (found == m_queue.begin())
        return EDownloading;
      else
        return EInQueue;
    }

    // second, check if this country has failed while downloading
    if (m_failedCountries.find(index) != m_failedCountries.end())
      return EDownloadFailed;

    TLocalAndRemoteSize size = CountryByIndex(index).Size();
    if (size.first == size.second)
    {
      if (size.second == 0)
        return EUnknown;
      else
        return EOnDisk;
    }

    return ENotDownloaded;
  }

  void Storage::DownloadCountry(TIndex const & index)
  {
    // check if we already downloading this country
    TQueue::const_iterator found = find(m_queue.begin(), m_queue.end(), index);
    if (found != m_queue.end())
    { // do nothing
      return;
    }
    // remove it from failed list
    m_failedCountries.erase(index);
    // add it into the queue
    m_queue.push_back(index);
    // and start download if necessary
    if (m_queue.size() == 1)
    {
      // reset total country's download progress
      TLocalAndRemoteSize size = CountryByIndex(index).Size();
      m_countryProgress = TDownloadProgress(0, size.second);

      DownloadNextCountryFromQueue();
    }
    else
    { // notify about "In Queue" status
      if (m_observerChange)
        m_observerChange(index);
    }
  }

  template <class TRemoveFn>
  class DeactivateMap
  {
    string m_workingDir;
    TRemoveFn & m_removeFn;
  public:
    DeactivateMap(TRemoveFn & removeFn) : m_removeFn(removeFn)
    {
      m_workingDir = GetPlatform().WritableDir();
    }
    void operator()(TTile const & tile)
    {
      string const file = m_workingDir + tile.first;
      m_removeFn(file);
    }
  };

  void Storage::DownloadNextCountryFromQueue()
  {
    while (!m_queue.empty())
    {
      TIndex index = m_queue.front();
      TTilesContainer const & tiles = CountryByIndex(index).Tiles();
      for (TTilesContainer::const_iterator it = tiles.begin(); it != tiles.end(); ++it)
      {
        if (!IsTileDownloaded(*it))
        {
          GetDownloadManager().DownloadFile(
              (UpdateBaseUrl() + UrlEncode(it->first)).c_str(),
              (GetPlatform().WritablePathForFile(it->first).c_str()),
              bind(&Storage::OnMapDownloadFinished, this, _1, _2),
              bind(&Storage::OnMapDownloadProgress, this, _1, _2),
              true);  // enabled resume support by default
          // notify GUI - new status for country, "Downloading"
          if (m_observerChange)
            m_observerChange(index);
          return;
        }
      }
      // continue with next country
      m_queue.pop_front();
      // reset total country's download progress
      if (!m_queue.empty())
        m_countryProgress = TDownloadProgress(0, CountryByIndex(m_queue.front()).Size().second);
      // and notify GUI - new status for country, "OnDisk"
      if (m_observerChange)
        m_observerChange(index);
    }
  }

  struct CancelDownloading
  {
    string const m_baseUrl;
    CancelDownloading(string const & baseUrl) : m_baseUrl(baseUrl) {}
    void operator()(TTile const & tile)
    {
      GetDownloadManager().CancelDownload((m_baseUrl + UrlEncode(tile.first)).c_str());
    }
  };

  class DeleteMap
  {
    string m_workingDir;
  public:
    DeleteMap()
    {
		  m_workingDir = GetPlatform().WritableDir();
    }
    /// @TODO do not delete other countries cells
    void operator()(TTile const & tile)
    {
      FileWriter::DeleteFileX(m_workingDir + tile.first);
    }
  };

  template <typename TRemoveFunc>
  void DeactivateAndDeleteCountry(Country const & country, TRemoveFunc removeFunc)
  {
    // deactivate from multiindex
    for_each(country.Tiles().begin(), country.Tiles().end(), DeactivateMap<TRemoveFunc>(removeFunc));
    // delete from disk
    for_each(country.Tiles().begin(), country.Tiles().end(), DeleteMap());
  }

  void Storage::DeleteCountry(TIndex const & index)
  {
    Country const & country = CountryByIndex(index);

    m2::RectD bounds;

    // check if we already downloading this country
    TQueue::iterator found = find(m_queue.begin(), m_queue.end(), index);
    if (found != m_queue.end())
    {
      if (found == m_queue.begin())
      { // stop download
        for_each(country.Tiles().begin(), country.Tiles().end(), CancelDownloading(UpdateBaseUrl()));
        // remove from the queue
        m_queue.erase(found);
        // start another download if the queue is not empty
        DownloadNextCountryFromQueue();
      }
      else
      { // remove from the queue
        m_queue.erase(found);
      }
    }
    else
    {
      // bounds are only updated if country was already activated before
      bounds = country.Bounds();
    }

    DeactivateAndDeleteCountry(country, m_removeMap);
    if (m_observerChange)
      m_observerChange(index);

    if (bounds != m2::RectD::GetEmptyRect())
      m_updateRect(bounds);
  }

  void Storage::ReInitCountries(bool forceReload)
  {
    if (forceReload)
      m_countries.Clear();

    if (m_countries.SiblingsCount() == 0)
    {
      TTilesContainer tiles;
      if (LoadTiles(tiles, GetPlatform().ReadPathForFile(DATA_UPDATE_FILE), m_currentVersion))
      {
        if (!LoadCountries(GetPlatform().ReadPathForFile(COUNTRIES_FILE), tiles, m_countries))
        {
          LOG(LWARNING, ("Can't load countries file", COUNTRIES_FILE));
        }
      }
      else
      {
        LOG(LWARNING, ("Can't load update file", DATA_UPDATE_FILE));
      }
    }
  }

  void Storage::Subscribe(TObserverChangeCountryFunction change, TObserverProgressFunction progress,
                          TUpdateRequestFunction updateRequest)
  {
    m_observerChange = change;
    m_observerProgress = progress;
    m_observerUpdateRequest = updateRequest;

    ReInitCountries(false);
  }

  void Storage::Unsubscribe()
  {
    m_observerChange.clear();
    m_observerProgress.clear();
    m_observerUpdateRequest.clear();
  }

  string FileFromUrl(string const & url)
  {
    return UrlDecode(url.substr(url.find_last_of('/') + 1, string::npos));
  }

  void Storage::OnMapDownloadFinished(char const * url, DownloadResult result)
  {
    if (m_queue.empty())
    {
      ASSERT(false, ("Invalid url?", url));
      return;
    }

    if (result != EHttpDownloadOk)
    {
      // remove failed country from the queue
      TIndex failedIndex = m_queue.front();
      m_queue.pop_front();
      m_failedCountries.insert(failedIndex);
      // notify GUI about failed country
      if (m_observerChange)
        m_observerChange(failedIndex);
    }
    else
    {
      TLocalAndRemoteSize size = CountryByIndex(m_queue.front()).Size();
      if (size.second != 0)
        m_countryProgress.first = size.first;
      // activate downloaded map piece
      string const datFile = GetPlatform().ReadPathForFile(FileFromUrl(url));
      m_addMap(datFile);

      feature::DataHeader header;
      header.Load(FilesContainerR(datFile).GetReader(HEADER_FILE_TAG));
      m_updateRect(header.GetBounds());
    }
    DownloadNextCountryFromQueue();
  }

  void Storage::OnMapDownloadProgress(char const * /*url*/, TDownloadProgress progress)
  {
    if (m_queue.empty())
    {
      ASSERT(false, ("queue can't be empty"));
      return;
    }

    if (m_observerProgress)
      m_observerProgress(m_queue.front(),
          TDownloadProgress(m_countryProgress.first + progress.first, m_countryProgress.second));
  }

  void Storage::CheckForUpdate()
  {
    // at this moment we support only binary update checks
    string const update = UpdateBaseUrl() + BINARY_UPDATE_FILE/*DATA_UPDATE_FILE*/;
    GetDownloadManager().CancelDownload(update.c_str());
    GetDownloadManager().DownloadFile(
        update.c_str(),
        (GetPlatform().WritablePathForFile(DATA_UPDATE_FILE)).c_str(),
        bind(&Storage::OnBinaryUpdateCheckFinished, this, _1, _2),
        TDownloadProgressFunction(), false);
  }

  void Storage::OnDataUpdateCheckFinished(char const * url, DownloadResult result)
  {
    if (result != EHttpDownloadOk)
    {
      LOG(LWARNING, ("Update check failed for url:", url));
      if (m_observerUpdateRequest)
        m_observerUpdateRequest(EDataCheckFailed, ErrorString(result));
    }
    else
    { // @TODO parse update file and notify GUI
    }

    // parse update file
//    TCountriesContainer tempCountries;
//    if (!LoadCountries(tempCountries, GetPlatform().WritablePathForFile(DATA_UPDATE_FILE)))
//    {
//      LOG(LWARNING, ("New application version should be downloaded, "
//                     "update file format can't be parsed"));
//      // @TODO: report to GUI
//      return;
//    }
//    // stop any active download, clear the queue, replace countries and notify GUI
//    if (!m_queue.empty())
//    {
//      CancelCountryDownload(CountryByIndex(m_queue.front()));
//      m_queue.clear();
//    }
//    m_countries.swap(tempCountries);
//    // @TODO report to GUI about reloading all countries
//    LOG(LINFO, ("Update check complete"));
  }

  void Storage::OnBinaryUpdateCheckFinished(char const * url, DownloadResult result)
  {
    if (result == EHttpDownloadFileNotFound)
    { // no binary update is available
      if (m_observerUpdateRequest)
        m_observerUpdateRequest(ENoAnyUpdateAvailable, "No update is available");
    }
    else if (result == EHttpDownloadOk)
    { // update is available!
      try
      {
        if (m_observerUpdateRequest)
        {
          string const updateTextFilePath = GetPlatform().ReadPathForFile(FileFromUrl(url));
          FileReader file(updateTextFilePath);
          m_observerUpdateRequest(ENewBinaryAvailable, file.ReadAsText());
        }
      }
      catch (std::exception const & e)
      {
        if (m_observerUpdateRequest)
          m_observerUpdateRequest(EBinaryCheckFailed,
                                    string("Error loading b-update text file ") + e.what());
      }
    }
    else
    { // connection error
      if (m_observerUpdateRequest)
        m_observerUpdateRequest(EBinaryCheckFailed, ErrorString(result));
    }
  }
}
<|endoftext|>


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

#include "chrome/browser/sync/notification_method.h"

#include "base/logging.h"

namespace browser_sync {

const NotificationMethod kDefaultNotificationMethod =
    NOTIFICATION_SERVER;

std::string NotificationMethodToString(
    NotificationMethod notification_method) {
  switch (notification_method) {
    case NOTIFICATION_LEGACY:
      return "NOTIFICATION_LEGACY";
      break;
    case NOTIFICATION_TRANSITIONAL:
      return "NOTIFICATION_TRANSITIONAL";
      break;
    case NOTIFICATION_NEW:
      return "NOTIFICATION_NEW";
      break;
    case NOTIFICATION_SERVER:
      return "NOTIFICATION_SERVER";
      break;
    default:
      LOG(WARNING) << "Unknown value for notification method: "
                   << notification_method;
      break;
  }
  return "<unknown notification method>";
}

NotificationMethod StringToNotificationMethod(const std::string& str) {
  if (str == "legacy") {
    return NOTIFICATION_LEGACY;
  } else if (str == "transitional") {
    return NOTIFICATION_TRANSITIONAL;
  } else if (str == "new") {
    return NOTIFICATION_NEW;
  } else if (str == "server") {
    return NOTIFICATION_SERVER;
  }
  LOG(WARNING) << "Unknown notification method \"" << str
               << "\"; using method "
               << NotificationMethodToString(kDefaultNotificationMethod);
  return kDefaultNotificationMethod;
}

}  // namespace browser_sync
<commit_msg>Revert 51494 - Set default sync notification method to "server".<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/sync/notification_method.h"

#include "base/logging.h"

namespace browser_sync {

// TODO(akalin): Eventually change this to NOTIFICATION_NEW.
const NotificationMethod kDefaultNotificationMethod =
    NOTIFICATION_TRANSITIONAL;

std::string NotificationMethodToString(
    NotificationMethod notification_method) {
  switch (notification_method) {
    case NOTIFICATION_LEGACY:
      return "NOTIFICATION_LEGACY";
      break;
    case NOTIFICATION_TRANSITIONAL:
      return "NOTIFICATION_TRANSITIONAL";
      break;
    case NOTIFICATION_NEW:
      return "NOTIFICATION_NEW";
      break;
    case NOTIFICATION_SERVER:
      return "NOTIFICATION_SERVER";
      break;
    default:
      LOG(WARNING) << "Unknown value for notification method: "
                   << notification_method;
      break;
  }
  return "<unknown notification method>";
}

NotificationMethod StringToNotificationMethod(const std::string& str) {
  if (str == "legacy") {
    return NOTIFICATION_LEGACY;
  } else if (str == "transitional") {
    return NOTIFICATION_TRANSITIONAL;
  } else if (str == "new") {
    return NOTIFICATION_NEW;
  } else if (str == "server") {
    return NOTIFICATION_SERVER;
  }
  LOG(WARNING) << "Unknown notification method \"" << str
               << "\"; using method "
               << NotificationMethodToString(kDefaultNotificationMethod);
  return kDefaultNotificationMethod;
}

}  // namespace browser_sync
<|endoftext|>


<commit_before>#include <assert.h>
#include <float.h>
#include <math.h>
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "bnet.hpp"
#include "matrix.hpp"
#include "rand.hpp"

#define VERBOSE 1
#define SAVE_NETWORKS 0

double dirichlet_score_family(SMatrix counts, SCPD cpd) {
  SMatrix ns = cpd->sizes, prior = cpd->dirichlet;
  SMatrix ns_self = ns->extract_indices(ns->rows - 1, ns->rows, 0, ns->cols);
  SMatrix pnc = counts + prior;
  SMatrix gamma_pnc = pnc->lgammaed(), gamma_prior = prior->lgammaed();
  SMatrix lu_mat = gamma_pnc - gamma_prior;
  SMatrix LU = lu_mat->sum_n_cols(ns_self->data[0]);
  SMatrix alpha_ij = prior->sum_n_cols(ns_self->data[0]);
  SMatrix N_ij = counts->sum_n_cols(ns_self->data[0]);
  SMatrix alpha_N = N_ij + alpha_ij;
  SMatrix LV = alpha_ij->lgammaed() - alpha_N->lgammaed();
  SMatrix LU_LV = LU + LV;
  double score = LU_LV->sumAllValue();
  return score;
}

int count_index(SMatrix sz, SMatrix sample_data, int col) {
  SMatrix mat_col = sample_data->extract_indices(0, sample_data->rows, col, col + 1);
  int index = 0;
  for (int i = 0, m = 1; i < mat_col->rows * mat_col->cols; m *= sz->data[i++]) {
    index += ((mat_col->data[i]) - 1) * m;
  }
  return index;
}

SMatrix compute_counts(SMatrix data, SMatrix sz) {
  SMatrix count = std::make_shared<Matrix>(sz->multiplyAllValues(), 1);
  for (int i = 0; i < data->cols; ++i) {
    count->data[count_index(sz, data, i)] += 1;
  }
  return count;
}

double log_marg_prob_node(SCPD cpd, SMatrix self_ev, SMatrix pev) {
  SMatrix data = pev->concat_rows(self_ev, false);
  SMatrix counts = compute_counts(data, cpd->sizes);
  return dirichlet_score_family(counts, cpd);
}

SMatrix prob_node(SCPD cpd, SMatrix self_ev, SMatrix pev) {
  SMatrix sample_data = pev->concat_rows(self_ev, false);
  SMatrix prob = std::make_shared<Matrix>(sample_data->rows, sample_data->cols);
  for (int i = 0; i < sample_data->cols; ++i) {
    SMatrix mat_col = sample_data->extract_indices(0, sample_data->rows, i, i + 1);
    int index = 0;
    auto dd = cpd->sizes->data;
    for (int j = 0, m = 1; j < mat_col->rows * mat_col->cols; m *= dd[j++]) {
      index += ((mat_col->data[j]) - 1) * m;
    }
    prob->data[i] = cpd->cpt->data[index];
  }
  return prob;
}

double log_prob_node(SCPD cpd, SMatrix self_ev, SMatrix pev) {
  double score = 0;
  SMatrix p = prob_node(cpd, self_ev, pev);
  for (int i = 0; i < p->rows * p->cols; ++i) {
    double d = p->data[i];
    score += d <= 0 ? DBL_MIN : log(d);
  }
  return score;
}

SCPD tabular_CPD(SMatrix dag, SMatrix ns, int self) {
  SCPD cpd = std::make_shared<CPD>();
  std::vector<int> ps = dag->adjacency_matrix_parents(self);
  ps.push_back(self);
  SMatrix fam_sz = std::make_shared<Matrix>(ps.size(), 1);
  for (int i = 0; i < ps.size(); ++i) {
    fam_sz->data[i] = ns->data[ps[i]];
  }
  cpd->sizes = fam_sz;
  SMatrix calc = fam_sz->extract_indices(0, ps.size() - 1, 0, 1);
  int psz = calc->multiplyAllValues();
  cpd->dirichlet = std::make_shared<Matrix>(
      fam_sz->multiplyAllValues(), 1,
      (1.0 / psz) * (1.0 / ns->data[self]));
  cpd->cpt = nullptr;
  return cpd;
}

double score_family(int j, std::vector<int> ps, SMatrix ns, std::vector<int> discrete, SMatrix data,
                    std::string scoring_fn) {
  SMatrix dag = std::make_shared<Matrix>(data->rows, data->rows);
  if (ps.size() > 0) {
    dag->set_list_index(1, ps, j, j + 1);
    // TODO: sort `ps` here.
  }
  SMatrix data_sub_1 = data->extract_indices(j, j + 1, 0, data->cols),
          data_sub_2 = data->extract_list_index(ps, 0, data->cols);
  SCPD cpd = tabular_CPD(dag, ns, j);
  double score;
  if (scoring_fn == "bayesian") {
    score = log_marg_prob_node(cpd, data_sub_1, data_sub_2);
  } else if (scoring_fn == "bic") {
    std::vector<int> fam(ps);
    fam.push_back(j);
    SMatrix data_sub_3 = data->extract_list_index(fam, 0, data->cols);
    SMatrix counts = compute_counts(data_sub_3, cpd->sizes);
    cpd->cpt = counts + cpd->dirichlet;
    cpd->cpt->mk_stochastic(ns);
    double L = log_prob_node(cpd, data_sub_1, data_sub_2);
    SMatrix sz = cpd->sizes;
    const int len = sz->rows * sz->cols;
    const int value = sz->data[len - 1];
    sz->set_position(len, value - 1);
    score = L - 0.5 * sz->multiplyAllValues() * log(data->cols);
    sz->set_position(len, value);
  } else {
    throw "dead in the water, mate";
  }
  return score;
}

template <class T>
std::vector<T> set_difference(std::vector<T> &a, std::vector<T> &b) {
  std::vector<T> c(a);
  for (auto &&v : b) {
    auto pos = std::find(c.begin(), c.end(), v);
    if (pos != c.end()) c.erase(pos);
  }
  return std::move(c);
}

SMatrix learn_struct_K2(SMatrix data, SMatrix ns, std::vector<int> order, std::string scoring_fn, int max_parents) {
  assert(order.size() == data->rows);
  const int n = data->rows;
  int max_fan_in = max_parents == 0 ? n : max_parents;
  std::vector<int> discrete;
  for (int i = 0; i < n; ++i) discrete.push_back(i);

  SMatrix dag = std::make_shared<Matrix>(n, n);
  int parent_order = 0;
  for (int i = 0; i < n; ++i) {
    std::vector<int> ps;
    const int j = order[i];
    double score = score_family(j, ps, ns, discrete, data, scoring_fn);
#if VERBOSE
    printf("\nnode %d, empty score %6.4f\n", j, score);
#endif
    for (; ps.size() <= max_fan_in;) {
      std::vector<int> order_sub(order.begin(), order.begin() + i);
      auto pps = set_difference<int>(order_sub, ps);
      int nps = pps.size();
      SMatrix pscore = std::make_shared<Matrix>(1, nps);
      for (int pi = 0; pi < nps; ++pi) {
        int p = pps[pi];
        ps.push_back(p);
        int n_index = ps.size() - 1;
        pscore->data[pi] = score_family(j, ps, ns, discrete, data, scoring_fn);
#if VERBOSE
        printf("considering adding %d to %d, score %6.4f\n", p, j, pscore->data[pi]);
#endif
        ps.erase(ps.begin() + n_index);
      }
      double best_pscore = -DBL_MAX;
      int best_p = -1;
      for (int i = 0; i < nps; ++i) {
        double d = pscore->data[i];
        if (d > best_pscore) {
          best_pscore = d;
          best_p = i;
        }
      }
      if (best_p == -1) {
        break;
      }
      best_p = pps[best_p];
      if (best_pscore > score) {
        score = best_pscore;
        ps.push_back(best_p);
#if VERBOSE
        printf("* adding %d to %d, score %6.4f\n", best_p, j, best_pscore);
#endif
      } else {
        break;
      }
    }
    if (ps.size() > 0) {
      dag->set_list_index(++parent_order, ps, j, j + 1);
    }
  }
  return dag;
}

int exec(int forkIndex, int forkSize, bool data_transposed, std::string f_data,
         int topologies, std::string f_output, std::string scoring_fn, int max_parents) {
  SMatrix data = load(f_data, !data_transposed),
          sz = data->create_sz();
  SMatrix orders = std::make_shared<Matrix>(data->rows * topologies, data->rows);
#if SAVE_NETWORKS
  SMatrix networks =
      std::make_shared<Matrix>(data->rows * topologies, data->rows * data->rows);
#endif

#pragma omp parallel for
  for (int r = 0; r < orders->rows; ++r) {
    int start = r / topologies;
    int *arr = new int[orders->cols];
    arr[0] = start;
    for (int i = 1; i < orders->cols; ++i) {
      arr[i] = i == start ? 0 : i;
    }
    shuffle_int(orders->cols - 1, arr + 1);
    for (int c = 0; c < orders->cols; ++c) {
      orders->inplace_set(r, c, arr[c]);
    }
    delete[] arr;
  }

  SMatrix consensus_network = std::make_shared<Matrix>(data->rows, data->rows);
  int cn_n_elements = consensus_network->rows * consensus_network->cols;

#pragma omp parallel for
  for (int o = 0; o < orders->rows; ++o) {
    SMatrix m_order = orders->list_elems_by_row_position(o + 1);
    std::vector<int> order = m_order->asVector<int>();
    SMatrix bnet = learn_struct_K2(data, sz, order, scoring_fn, max_parents);
    assert(consensus_network->rows == bnet->rows);
    assert(consensus_network->cols == bnet->cols);

#pragma omp critical
    for (int i = 0; i < cn_n_elements; ++i) {
      consensus_network->data[i] += bnet->data[i] ? 1 : 0;
    }

#if SAVE_NETWORKS
    for (int i = 0; i < cn_n_elements; ++i) {
      networks->data[i + cn_n_elements * o] = bnet->data[i];
    }
#endif
  }

  if (forkIndex == 0) {
    consensus_network->save(f_output);
#if SAVE_NETWORKS
    networks->save("networks.csv");
    orders->save("topologies.csv");
#endif
  }
  return 0;
}

int main(int argc, char **argv) {
  int forkIndex = 0, forkSize = 1;

  srand(time(NULL) ^ forkIndex);
  int threads = 1, topologies = 1, max_parents = 0;
  bool data_transposed = false;
  std::string data, output = "consensus.csv";
  std::string scoring_fn = "bayesian";
  int c;
  while ((c = getopt(argc, argv, "Thp:d:t:o:s:")) != -1) {
    switch (c) {
    case 'T': {
      data_transposed = true;
      break;
    }
    case 'p': {
      threads = atoi(optarg);
      assert(threads > 0);
      assert(threads <= omp_get_num_procs());
      break;
    }
    case 'm': {
      max_parents = atoi(optarg);
      assert(max_parents >= 0);
      break;
    }
    case 'd': {
      data = optarg;
      break;
    }
    case 't': {
      topologies = atoi(optarg);
      break;
    }
    case 'o': {
      output = optarg;
      break;
    }
    case 's': {
      scoring_fn = optarg;
      break;
    }
    case 'h':
    default: {
      puts(
          ": -p <num_threads> -d <data file> -t <topologies per gene> -o "
          "<output file> -m <max parents>");
      puts("~ -T (reads matrix transposed)");
      return 1;
    }
    }
  }
  if (data.size() < 1) {
    puts("You must send a data file using -d <file name>.");
    return 1;
  }
  omp_set_num_threads(threads);
  int status = exec(forkIndex, forkSize, data_transposed, data, topologies,
                    output, scoring_fn, max_parents);
  return status;
}
<commit_msg>Turn off verbose<commit_after>#include <assert.h>
#include <float.h>
#include <math.h>
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "bnet.hpp"
#include "matrix.hpp"
#include "rand.hpp"

#define VERBOSE 0
#define SAVE_NETWORKS 0

double dirichlet_score_family(SMatrix counts, SCPD cpd) {
  SMatrix ns = cpd->sizes, prior = cpd->dirichlet;
  SMatrix ns_self = ns->extract_indices(ns->rows - 1, ns->rows, 0, ns->cols);
  SMatrix pnc = counts + prior;
  SMatrix gamma_pnc = pnc->lgammaed(), gamma_prior = prior->lgammaed();
  SMatrix lu_mat = gamma_pnc - gamma_prior;
  SMatrix LU = lu_mat->sum_n_cols(ns_self->data[0]);
  SMatrix alpha_ij = prior->sum_n_cols(ns_self->data[0]);
  SMatrix N_ij = counts->sum_n_cols(ns_self->data[0]);
  SMatrix alpha_N = N_ij + alpha_ij;
  SMatrix LV = alpha_ij->lgammaed() - alpha_N->lgammaed();
  SMatrix LU_LV = LU + LV;
  double score = LU_LV->sumAllValue();
  return score;
}

int count_index(SMatrix sz, SMatrix sample_data, int col) {
  SMatrix mat_col = sample_data->extract_indices(0, sample_data->rows, col, col + 1);
  int index = 0;
  for (int i = 0, m = 1; i < mat_col->rows * mat_col->cols; m *= sz->data[i++]) {
    index += ((mat_col->data[i]) - 1) * m;
  }
  return index;
}

SMatrix compute_counts(SMatrix data, SMatrix sz) {
  SMatrix count = std::make_shared<Matrix>(sz->multiplyAllValues(), 1);
  for (int i = 0; i < data->cols; ++i) {
    count->data[count_index(sz, data, i)] += 1;
  }
  return count;
}

double log_marg_prob_node(SCPD cpd, SMatrix self_ev, SMatrix pev) {
  SMatrix data = pev->concat_rows(self_ev, false);
  SMatrix counts = compute_counts(data, cpd->sizes);
  return dirichlet_score_family(counts, cpd);
}

SMatrix prob_node(SCPD cpd, SMatrix self_ev, SMatrix pev) {
  SMatrix sample_data = pev->concat_rows(self_ev, false);
  SMatrix prob = std::make_shared<Matrix>(sample_data->rows, sample_data->cols);
  for (int i = 0; i < sample_data->cols; ++i) {
    SMatrix mat_col = sample_data->extract_indices(0, sample_data->rows, i, i + 1);
    int index = 0;
    auto dd = cpd->sizes->data;
    for (int j = 0, m = 1; j < mat_col->rows * mat_col->cols; m *= dd[j++]) {
      index += ((mat_col->data[j]) - 1) * m;
    }
    prob->data[i] = cpd->cpt->data[index];
  }
  return prob;
}

double log_prob_node(SCPD cpd, SMatrix self_ev, SMatrix pev) {
  double score = 0;
  SMatrix p = prob_node(cpd, self_ev, pev);
  for (int i = 0; i < p->rows * p->cols; ++i) {
    double d = p->data[i];
    score += d <= 0 ? DBL_MIN : log(d);
  }
  return score;
}

SCPD tabular_CPD(SMatrix dag, SMatrix ns, int self) {
  SCPD cpd = std::make_shared<CPD>();
  std::vector<int> ps = dag->adjacency_matrix_parents(self);
  ps.push_back(self);
  SMatrix fam_sz = std::make_shared<Matrix>(ps.size(), 1);
  for (int i = 0; i < ps.size(); ++i) {
    fam_sz->data[i] = ns->data[ps[i]];
  }
  cpd->sizes = fam_sz;
  SMatrix calc = fam_sz->extract_indices(0, ps.size() - 1, 0, 1);
  int psz = calc->multiplyAllValues();
  cpd->dirichlet = std::make_shared<Matrix>(
      fam_sz->multiplyAllValues(), 1,
      (1.0 / psz) * (1.0 / ns->data[self]));
  cpd->cpt = nullptr;
  return cpd;
}

double score_family(int j, std::vector<int> ps, SMatrix ns, std::vector<int> discrete, SMatrix data,
                    std::string scoring_fn) {
  SMatrix dag = std::make_shared<Matrix>(data->rows, data->rows);
  if (ps.size() > 0) {
    dag->set_list_index(1, ps, j, j + 1);
    // TODO: sort `ps` here.
  }
  SMatrix data_sub_1 = data->extract_indices(j, j + 1, 0, data->cols),
          data_sub_2 = data->extract_list_index(ps, 0, data->cols);
  SCPD cpd = tabular_CPD(dag, ns, j);
  double score;
  if (scoring_fn == "bayesian") {
    score = log_marg_prob_node(cpd, data_sub_1, data_sub_2);
  } else if (scoring_fn == "bic") {
    std::vector<int> fam(ps);
    fam.push_back(j);
    SMatrix data_sub_3 = data->extract_list_index(fam, 0, data->cols);
    SMatrix counts = compute_counts(data_sub_3, cpd->sizes);
    cpd->cpt = counts + cpd->dirichlet;
    cpd->cpt->mk_stochastic(ns);
    double L = log_prob_node(cpd, data_sub_1, data_sub_2);
    SMatrix sz = cpd->sizes;
    const int len = sz->rows * sz->cols;
    const int value = sz->data[len - 1];
    sz->set_position(len, value - 1);
    score = L - 0.5 * sz->multiplyAllValues() * log(data->cols);
    sz->set_position(len, value);
  } else {
    throw "dead in the water, mate";
  }
  return score;
}

template <class T>
std::vector<T> set_difference(std::vector<T> &a, std::vector<T> &b) {
  std::vector<T> c(a);
  for (auto &&v : b) {
    auto pos = std::find(c.begin(), c.end(), v);
    if (pos != c.end()) c.erase(pos);
  }
  return std::move(c);
}

SMatrix learn_struct_K2(SMatrix data, SMatrix ns, std::vector<int> order, std::string scoring_fn, int max_parents) {
  assert(order.size() == data->rows);
  const int n = data->rows;
  int max_fan_in = max_parents == 0 ? n : max_parents;
  std::vector<int> discrete;
  for (int i = 0; i < n; ++i) discrete.push_back(i);

  SMatrix dag = std::make_shared<Matrix>(n, n);
  int parent_order = 0;
  for (int i = 0; i < n; ++i) {
    std::vector<int> ps;
    const int j = order[i];
    double score = score_family(j, ps, ns, discrete, data, scoring_fn);
#if VERBOSE
    printf("\nnode %d, empty score %6.4f\n", j, score);
#endif
    for (; ps.size() <= max_fan_in;) {
      std::vector<int> order_sub(order.begin(), order.begin() + i);
      auto pps = set_difference<int>(order_sub, ps);
      int nps = pps.size();
      SMatrix pscore = std::make_shared<Matrix>(1, nps);
      for (int pi = 0; pi < nps; ++pi) {
        int p = pps[pi];
        ps.push_back(p);
        int n_index = ps.size() - 1;
        pscore->data[pi] = score_family(j, ps, ns, discrete, data, scoring_fn);
#if VERBOSE
        printf("considering adding %d to %d, score %6.4f\n", p, j, pscore->data[pi]);
#endif
        ps.erase(ps.begin() + n_index);
      }
      double best_pscore = -DBL_MAX;
      int best_p = -1;
      for (int i = 0; i < nps; ++i) {
        double d = pscore->data[i];
        if (d > best_pscore) {
          best_pscore = d;
          best_p = i;
        }
      }
      if (best_p == -1) {
        break;
      }
      best_p = pps[best_p];
      if (best_pscore > score) {
        score = best_pscore;
        ps.push_back(best_p);
#if VERBOSE
        printf("* adding %d to %d, score %6.4f\n", best_p, j, best_pscore);
#endif
      } else {
        break;
      }
    }
    if (ps.size() > 0) {
      dag->set_list_index(++parent_order, ps, j, j + 1);
    }
  }
  return dag;
}

int exec(int forkIndex, int forkSize, bool data_transposed, std::string f_data,
         int topologies, std::string f_output, std::string scoring_fn, int max_parents) {
  SMatrix data = load(f_data, !data_transposed),
          sz = data->create_sz();
  SMatrix orders = std::make_shared<Matrix>(data->rows * topologies, data->rows);
#if SAVE_NETWORKS
  SMatrix networks =
      std::make_shared<Matrix>(data->rows * topologies, data->rows * data->rows);
#endif

#pragma omp parallel for
  for (int r = 0; r < orders->rows; ++r) {
    int start = r / topologies;
    int *arr = new int[orders->cols];
    arr[0] = start;
    for (int i = 1; i < orders->cols; ++i) {
      arr[i] = i == start ? 0 : i;
    }
    shuffle_int(orders->cols - 1, arr + 1);
    for (int c = 0; c < orders->cols; ++c) {
      orders->inplace_set(r, c, arr[c]);
    }
    delete[] arr;
  }

  SMatrix consensus_network = std::make_shared<Matrix>(data->rows, data->rows);
  int cn_n_elements = consensus_network->rows * consensus_network->cols;

#pragma omp parallel for
  for (int o = 0; o < orders->rows; ++o) {
    SMatrix m_order = orders->list_elems_by_row_position(o + 1);
    std::vector<int> order = m_order->asVector<int>();
    SMatrix bnet = learn_struct_K2(data, sz, order, scoring_fn, max_parents);
    assert(consensus_network->rows == bnet->rows);
    assert(consensus_network->cols == bnet->cols);

#pragma omp critical
    for (int i = 0; i < cn_n_elements; ++i) {
      consensus_network->data[i] += bnet->data[i] ? 1 : 0;
    }

#if SAVE_NETWORKS
    for (int i = 0; i < cn_n_elements; ++i) {
      networks->data[i + cn_n_elements * o] = bnet->data[i];
    }
#endif
  }

  if (forkIndex == 0) {
    consensus_network->save(f_output);
#if SAVE_NETWORKS
    networks->save("networks.csv");
    orders->save("topologies.csv");
#endif
  }
  return 0;
}

int main(int argc, char **argv) {
  int forkIndex = 0, forkSize = 1;

  srand(time(NULL) ^ forkIndex);
  int threads = 1, topologies = 1, max_parents = 0;
  bool data_transposed = false;
  std::string data, output = "consensus.csv";
  std::string scoring_fn = "bayesian";
  int c;
  while ((c = getopt(argc, argv, "Thp:d:t:o:s:")) != -1) {
    switch (c) {
    case 'T': {
      data_transposed = true;
      break;
    }
    case 'p': {
      threads = atoi(optarg);
      assert(threads > 0);
      assert(threads <= omp_get_num_procs());
      break;
    }
    case 'm': {
      max_parents = atoi(optarg);
      assert(max_parents >= 0);
      break;
    }
    case 'd': {
      data = optarg;
      break;
    }
    case 't': {
      topologies = atoi(optarg);
      break;
    }
    case 'o': {
      output = optarg;
      break;
    }
    case 's': {
      scoring_fn = optarg;
      break;
    }
    case 'h':
    default: {
      puts(
          ": -p <num_threads> -d <data file> -t <topologies per gene> -o "
          "<output file> -m <max parents>");
      puts("~ -T (reads matrix transposed)");
      return 1;
    }
    }
  }
  if (data.size() < 1) {
    puts("You must send a data file using -d <file name>.");
    return 1;
  }
  omp_set_num_threads(threads);
  int status = exec(forkIndex, forkSize, data_transposed, data, topologies,
                    output, scoring_fn, max_parents);
  return status;
}
<|endoftext|>


<commit_before>/** \file
 * Implements safer c++ wrappers for the sysctl() interface.
 */

#ifndef _POWERDXX_SYS_SYSCTL_HPP_
#define _POWERDXX_SYS_SYSCTL_HPP_

#include "error.hpp"       /* sys::sc_error */

#include <sys/types.h>     /* sysctl() */
#include <sys/sysctl.h>    /* sysctl() */

namespace sys {

/**
 * This namespace contains safer c++ wrappers for the sysctl() interface.
 *
 * The template class Sysctl represents a sysctl address and offers
 * handles to retrieve or set the stored value.
 */
namespace ctl {

/**
 * Management Information Base identifier type (see sysctl(3)).
 */
typedef int mib_t;

/**
 * Represents a sysctl MIB address.
 *
 * @tparam MibDepth
 *	The maximum allowed MIB depth
 */
template <size_t MibDepth>
class Sysctl {
	private:
	/**
	 * Stores the MIB address.
	 */
	mib_t mib[MibDepth];

	public:
	/**
	 * The default constructor.
	 *
	 * This is available to defer initialisation to a later moment.
	 * This might be useful when initialising global or static
	 * instances by a character string repesented name.
	 */
	constexpr Sysctl() : mib{} {}

	/**
	 * Initialise the MIB address from a character string.
	 *
	 * @param name
	 *	The name of the sysctl
	 * @throws sc_error
	 *	May throw an exception if the addressed sysct does
	 *	not exist or if the address is too long to store
	 */
	Sysctl(char const * const name) {
		size_t length = MibDepth;
		if (::sysctlnametomib(name, this->mib, &length) == -1) {
			throw sc_error{errno};
		}
	}

	/**
	 * Initialise the MIB address directly.
	 *
	 * Some important sysctl values have a fixed address that
	 * can be initialised at compile time with a noexcept guarantee.
	 *
	 * Spliting the MIB address into head and tail makes sure
	 * that `Sysctl(char *)` does not match the template and is
	 * instead implicitly cast to invoke `Sysctl(char const *)`.
	 *
	 * @tparam Tail
	 *	The types of the trailing MIB address values (must
	 *	be mib_t)
	 * @param head,tail
	 *	The mib
	 */
	template <typename... Tail>
	constexpr Sysctl(mib_t const head, Tail const... tail) noexcept :
	    mib{head, tail...} {
		static_assert(MibDepth >= sizeof...(Tail) + 1,
		              "The number of MIB addresses must not exceed the MIB depth");
	}

	/**
	 * Update the given buffer with a value retrieved from the
	 * sysctl.
	 *
	 * @param buf,bufsize
	 *	The target buffer and its size
	 * @throws sc_error
	 *	Throws if value retrieval fails or is incomplete,
	 *	e.g. because the value does not fit into the target
	 *	buffer
	 */
	void update(void * const buf, size_t const bufsize) const {
		auto len = bufsize;
		if (::sysctl(this->mib, MibDepth, buf, &len, nullptr, 0)
		    == -1) {
			throw sc_error{errno};
		}
	}

	/**
	 * Update the given value with a value retreived from the
	 * sysctl.
	 *
	 * @tparam T
	 *	The type store the sysctl value in
	 * @param value
	 *	A reference to the target value
	 * @throws sc_error
	 *	Throws if value retrieval fails or is incomplete,
	 *	e.g. because the value does not fit into the target
	 *	type
	 */
	template <typename T>
	void update(T & value) const {
		update(&value, sizeof(T));
	}

	/**
	 * Retrieve an array from the sysctl address.
	 *
	 * This is useful to retrieve variable length sysctls, like
	 * characer strings.
	 *
	 * @tparam T
	 *	The type stored in the array
	 * @return
	 *	And array of T with the right length to store the
	 *	whole sysctl value
	 * @throws sc_error
	 *	May throw if the size of the sysctl increases after
	 *	the length was queried
	 */
	template <typename T>
	std::unique_ptr<T[]> get() const {
		size_t len = 0;
		if (::sysctl(this->mib, MibDepth, nullptr, &len, nullptr, 0)
		    == -1) {
			throw sc_error{errno};
		}
		auto result = std::unique_ptr<T[]>(new T[len / sizeof(T)]);
		update(result.get(), len);
		return result;
	}

	/**
	 * Update the the sysctl value with the given buffer.
	 *
	 * @param buf,bufsize
	 *	The source buffer
	 * @throws sc_error
	 *	If the source buffer cannot be stored in the sysctl
	 */
	void set(void const * const buf, size_t const bufsize) {
		if (::sysctl(this->mib, MibDepth, nullptr, nullptr,
		             buf, bufsize) == -1) {
			throw sc_error{errno};
		}
	}

	/**
	 * Update the the sysctl value with the given value.
	 *
	 * @tparam T
	 *	The value type
	 * @param value
	 *	The value to set the sysctl to
	 */
	template <typename T>
	void set(T const & value) {
		set(&value, sizeof(T));
	}

};

template <typename... MibTs>
constexpr Sysctl<sizeof...(MibTs)> make_Sysctl(MibTs const... mib) {
	return {mib...};
}

template <size_t MibDepth, typename T>
class SysctlValue {
	private:
	T value;
	Sysctl<MibDepth> sysctl;

	public:
	template <typename... SysctlArgs>
	constexpr SysctlValue(T const & value, SysctlArgs const &... args) :
		value{value}, sysctl{args...} {};

	SysctlValue & operator =(T const & value) {
		this->value = value;
		this->sysctl.set(this->value);
		return *this;
	}

	operator T const &() const {
		return this->value;
	}

	void update() {
		this->sysctl.update(this->value);
	}
};

template <typename T, typename... MibTs>
constexpr SysctlValue<sizeof...(MibTs), T>
make_SysctlValue(T const & value, MibTs const... addr) {
	return {value, addr...};
}

} /* namespace ctl */
} /* namespace sys */

#endif /* _POWERDXX_SYS_SYSCTL_HPP_ */
<commit_msg>Replace SysctlValue with Once and Sync<commit_after>/** \file
 * Implements safer c++ wrappers for the sysctl() interface.
 */

#ifndef _POWERDXX_SYS_SYSCTL_HPP_
#define _POWERDXX_SYS_SYSCTL_HPP_

#include "error.hpp"       /* sys::sc_error */

#include <sys/types.h>     /* sysctl() */
#include <sys/sysctl.h>    /* sysctl() */

namespace sys {

/**
 * This namespace contains safer c++ wrappers for the sysctl() interface.
 *
 * The template class Sysctl represents a sysctl address and offers
 * handles to retrieve or set the stored value.
 */
namespace ctl {

/**
 * Management Information Base identifier type (see sysctl(3)).
 */
typedef int mib_t;

/**
 * Represents a sysctl MIB address.
 *
 * @tparam MibDepth
 *	The maximum allowed MIB depth
 */
template <size_t MibDepth>
class Sysctl {
	private:
	/**
	 * Stores the MIB address.
	 */
	mib_t mib[MibDepth];

	public:
	/**
	 * The default constructor.
	 *
	 * This is available to defer initialisation to a later moment.
	 * This might be useful when initialising global or static
	 * instances by a character string repesented name.
	 */
	constexpr Sysctl() : mib{} {}

	/**
	 * Initialise the MIB address from a character string.
	 *
	 * @param name
	 *	The name of the sysctl
	 * @throws sc_error
	 *	May throw an exception if the addressed sysct does
	 *	not exist or if the address is too long to store
	 */
	Sysctl(char const * const name) {
		size_t length = MibDepth;
		if (::sysctlnametomib(name, this->mib, &length) == -1) {
			throw sc_error{errno};
		}
	}

	/**
	 * Initialise the MIB address directly.
	 *
	 * Some important sysctl values have a fixed address that
	 * can be initialised at compile time with a noexcept guarantee.
	 *
	 * Spliting the MIB address into head and tail makes sure
	 * that `Sysctl(char *)` does not match the template and is
	 * instead implicitly cast to invoke `Sysctl(char const *)`.
	 *
	 * @tparam Tail
	 *	The types of the trailing MIB address values (must
	 *	be mib_t)
	 * @param head,tail
	 *	The mib
	 */
	template <typename... Tail>
	constexpr Sysctl(mib_t const head, Tail const... tail) noexcept :
	    mib{head, tail...} {
		static_assert(MibDepth >= sizeof...(Tail) + 1,
		              "The number of MIB addresses must not exceed the MIB depth");
	}

	/**
	 * Update the given buffer with a value retrieved from the
	 * sysctl.
	 *
	 * @param buf,bufsize
	 *	The target buffer and its size
	 * @throws sc_error
	 *	Throws if value retrieval fails or is incomplete,
	 *	e.g. because the value does not fit into the target
	 *	buffer
	 */
	void update(void * const buf, size_t const bufsize) const {
		auto len = bufsize;
		if (::sysctl(this->mib, MibDepth, buf, &len, nullptr, 0)
		    == -1) {
			throw sc_error{errno};
		}
	}

	/**
	 * Update the given value with a value retreived from the
	 * sysctl.
	 *
	 * @tparam T
	 *	The type store the sysctl value in
	 * @param value
	 *	A reference to the target value
	 * @throws sc_error
	 *	Throws if value retrieval fails or is incomplete,
	 *	e.g. because the value does not fit into the target
	 *	type
	 */
	template <typename T>
	void update(T & value) const {
		update(&value, sizeof(T));
	}

	/**
	 * Retrieve an array from the sysctl address.
	 *
	 * This is useful to retrieve variable length sysctls, like
	 * characer strings.
	 *
	 * @tparam T
	 *	The type stored in the array
	 * @return
	 *	And array of T with the right length to store the
	 *	whole sysctl value
	 * @throws sc_error
	 *	May throw if the size of the sysctl increases after
	 *	the length was queried
	 */
	template <typename T>
	std::unique_ptr<T[]> get() const {
		size_t len = 0;
		if (::sysctl(this->mib, MibDepth, nullptr, &len, nullptr, 0)
		    == -1) {
			throw sc_error{errno};
		}
		auto result = std::unique_ptr<T[]>(new T[len / sizeof(T)]);
		update(result.get(), len);
		return result;
	}

	/**
	 * Update the the sysctl value with the given buffer.
	 *
	 * @param buf,bufsize
	 *	The source buffer
	 * @throws sc_error
	 *	If the source buffer cannot be stored in the sysctl
	 */
	void set(void const * const buf, size_t const bufsize) {
		if (::sysctl(this->mib, MibDepth, nullptr, nullptr,
		             buf, bufsize) == -1) {
			throw sc_error{errno};
		}
	}

	/**
	 * Update the the sysctl value with the given value.
	 *
	 * @tparam T
	 *	The value type
	 * @param value
	 *	The value to set the sysctl to
	 */
	template <typename T>
	void set(T const & value) {
		set(&value, sizeof(T));
	}

};

template <typename T, class SysctlT>
class Sync {
	private:
	SysctlT sysctl;

	public:
	constexpr Sync(SysctlT const & sysctl) noexcept : sysctl{sysctl} {}

	Sync & operator =(T const & value) {
		this->sysctl.set(value);
		return *this;
	}

	operator T () const {
		T value;
		this->sysctl.update(value);
		return value;
	}
};

template <typename T, size_t MibDepth>
using SysctlSync = Sync<T, Sysctl<MibDepth>>;

template <typename T, class SysctlT>
class Once {
	private:
	T value;

	public:
	Once(T const & value, SysctlT const & sysctl) noexcept {
		try {
			sysctl.update(this->value);
		} catch (sc_error) {
			this->value = value;
		}
	}

	operator T const &() const {
		return this->value;
	}
};

template <typename T, size_t MibDepth>
using SysctlOnce = Once<T, Sysctl<MibDepth>>;

template <typename T, class SysctlT>
constexpr Once<T, SysctlT> once(T const & value, SysctlT const & sysctl)
    noexcept {
	return {value, sysctl};
}

} /* namespace ctl */
} /* namespace sys */

#endif /* _POWERDXX_SYS_SYSCTL_HPP_ */
<|endoftext|>


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

#include "chrome/browser/views/browser_bubble.h"

#include "app/l10n_util_win.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "views/widget/root_view.h"
#include "views/widget/widget_win.h"
#include "views/window/window.h"

class BubbleWidget : public views::WidgetWin {
 public:
  explicit BubbleWidget(BrowserBubble* bubble)
      : bubble_(bubble), closed_(false) {
  }

  void Show(bool activate) {
    if (activate)
      ShowWindow(SW_SHOW);
    else
      views::WidgetWin::Show();
  }

  void Close() {
    if (closed_)
      return;
    closed_ = true;
    if (IsActive()) {
      BrowserBubble::Delegate* delegate = bubble_->delegate();
      if (delegate)
        delegate->BubbleLostFocus(bubble_);
    }
    views::WidgetWin::Close();
  }

  void Hide() {
    if (IsActive()) {
      BrowserBubble::Delegate* delegate = bubble_->delegate();
      if (delegate)
        delegate->BubbleLostFocus(bubble_);
    }
    views::WidgetWin::Hide();
  }

  void OnActivate(UINT action, BOOL minimized, HWND window) {
    BrowserBubble::Delegate* delegate = bubble_->delegate();
    if (!delegate) {
      if (action == WA_INACTIVE && !closed_) {
        bubble_->DetachFromBrowser();
        delete bubble_;
      }
      return;
    }

    if (action == WA_INACTIVE && !closed_) {
      delegate->BubbleLostFocus(bubble_);
    } else if (action == WA_ACTIVE) {
      delegate->BubbleGotFocus(bubble_);
    }
  }

 private:
  bool closed_;
  BrowserBubble* bubble_;
};

void BrowserBubble::InitPopup() {
  // popup_ is a Widget, but we need to do some WidgetWin stuff first, then
  // we'll assign it into popup_.
  views::WidgetWin* pop = new BubbleWidget(this);
  pop->set_window_style(WS_POPUP);
  pop->Init(frame_native_view_, bounds_);
  pop->SetContentsView(view_);

  popup_ = pop;
  Reposition();
  AttachToBrowser();
}

void BrowserBubble::MovePopup(int x, int y, int w, int h) {
  views::WidgetWin* pop = static_cast<views::WidgetWin*>(popup_);
  pop->MoveWindow(x, y, w, h);
}

void BrowserBubble::Show(bool activate) {
  if (visible_)
    return;
  BubbleWidget* pop = static_cast<BubbleWidget*>(popup_);
  pop->Show(activate);
  visible_ = true;
}

void BrowserBubble::Hide() {
  if (!visible_)
    return;
  views::WidgetWin* pop = static_cast<views::WidgetWin*>(popup_);
  pop->Hide();
  visible_ = false;
}
<commit_msg>Mostly fixes black flashing that happens during popup resize.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/views/browser_bubble.h"

#include "app/l10n_util_win.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "views/widget/root_view.h"
#include "views/widget/widget_win.h"
#include "views/window/window.h"

class BubbleWidget : public views::WidgetWin {
 public:
  explicit BubbleWidget(BrowserBubble* bubble)
      : bubble_(bubble), closed_(false) {
    set_window_style(WS_POPUP | WS_CLIPCHILDREN);
    set_window_ex_style(WS_EX_TOOLWINDOW);
  }

  void Show(bool activate) {
    if (activate)
      ShowWindow(SW_SHOW);
    else
      views::WidgetWin::Show();
  }

  void Close() {
    if (closed_)
      return;
    closed_ = true;
    if (IsActive()) {
      BrowserBubble::Delegate* delegate = bubble_->delegate();
      if (delegate)
        delegate->BubbleLostFocus(bubble_);
    }
    views::WidgetWin::Close();
  }

  void Hide() {
    if (IsActive()) {
      BrowserBubble::Delegate* delegate = bubble_->delegate();
      if (delegate)
        delegate->BubbleLostFocus(bubble_);
    }
    views::WidgetWin::Hide();
  }

  void OnActivate(UINT action, BOOL minimized, HWND window) {
    BrowserBubble::Delegate* delegate = bubble_->delegate();
    if (!delegate) {
      if (action == WA_INACTIVE && !closed_) {
        bubble_->DetachFromBrowser();
        delete bubble_;
      }
      return;
    }

    if (action == WA_INACTIVE && !closed_) {
      delegate->BubbleLostFocus(bubble_);
    } else if (action == WA_ACTIVE) {
      delegate->BubbleGotFocus(bubble_);
    }
  }

 private:
  bool closed_;
  BrowserBubble* bubble_;
};

void BrowserBubble::InitPopup() {
  // popup_ is a Widget, but we need to do some WidgetWin stuff first, then
  // we'll assign it into popup_.
  views::WidgetWin* pop = new BubbleWidget(this);
  pop->Init(frame_native_view_, bounds_);
  pop->SetContentsView(view_);

  popup_ = pop;
  Reposition();
  AttachToBrowser();
}

void BrowserBubble::MovePopup(int x, int y, int w, int h) {
  views::WidgetWin* pop = static_cast<views::WidgetWin*>(popup_);
  pop->SetBounds(gfx::Rect(x, y, w, h));
}

void BrowserBubble::Show(bool activate) {
  if (visible_)
    return;
  BubbleWidget* pop = static_cast<BubbleWidget*>(popup_);
  pop->Show(activate);
  visible_ = true;
}

void BrowserBubble::Hide() {
  if (!visible_)
    return;
  views::WidgetWin* pop = static_cast<views::WidgetWin*>(popup_);
  pop->Hide();
  visible_ = false;
}
<|endoftext|>