<commit_before>#include "page_manager.h"
#include "../utils/asyncworker.h"
#include "../utils/fs.h"
#include "../utils/locker.h"
#include "../utils/utils.h"
#include "manifest.h"
#include "page.h"

#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <condition_variable>
#include <cstring>
#include <functional>
#include <memory>
#include <queue>
#include <thread>

const std::string MANIFEST_FILE_NAME = "Manifest";

using namespace dariadb::storage;
dariadb::storage::PageManager *PageManager::_instance = nullptr;
// PM
class PageManager::Private /*:public dariadb::utils::AsyncWorker<Chunk_Ptr>*/ {
public:
  Private(const PageManager::Params &param)
      : _cur_page(nullptr), _param(param),
        _manifest(utils::fs::append_path(param.path, MANIFEST_FILE_NAME)) {
    update_id = false;
    last_id = 0;

    _cur_page = open_last_openned();
    /*this->start_async();*/
  }

  Page *open_last_openned() {
    if (!utils::fs::path_exists(_param.path)) {
      return nullptr;
    }
    auto pages = _manifest.page_list();

    for (auto n : pages) {
      auto file_name = utils::fs::append_path(_param.path, n);
      auto hdr = Page::readHeader(file_name);
      if (!hdr.is_full) {
        auto res = Page::open(file_name);
        update_id = false;
        return res;
      } else {
        last_id = std::max(last_id, hdr.max_chunk_id);
        update_id = true;
      }
    }
    return nullptr;
  }

  ~Private() {
    /* this->stop_async();*/

    if (_cur_page != nullptr) {
      delete _cur_page;
      _cur_page = nullptr;
    }
  }

  uint64_t calc_page_size() const {
    auto sz_info = _param.chunk_per_storage * sizeof(ChunkIndexInfo);
    auto sz_buffers = _param.chunk_per_storage * _param.chunk_size;
    return sizeof(PageHeader) + sz_buffers + sz_info;
  }

  Page *create_page() {
    if (!dariadb::utils::fs::path_exists(_param.path)) {
      dariadb::utils::fs::mkdir(_param.path);
    }

    Page *res = nullptr; // open_last_openned();

    // if (res == nullptr) {
    std::string page_name = utils::fs::random_file_name(".page");
    std::string file_name =
        dariadb::utils::fs::append_path(_param.path, page_name);
    auto sz = calc_page_size();
    res = Page::create(file_name, sz, _param.chunk_per_storage,
                       _param.chunk_size);
    _manifest.page_append(page_name);
    if (update_id) {
      res->header->max_chunk_id = last_id;
    }
    //}

    return res;
  }
  // PM
  void flush() { /*this->flush_async();*/
  }
  // void call_async(const Chunk_Ptr &ch) override { /*write_to_page(ch);*/ }

  Page *get_cur_page() {
    if (_cur_page == nullptr) {
      _cur_page = create_page();
    }
    return _cur_page;
  }

  bool minMaxTime(dariadb::Id id, dariadb::Time *minResult,
                  dariadb::Time *maxResult) {
    boost::shared_lock<boost::shared_mutex> lg(_locker);

    auto pages = pages_by_filter([id](const IndexHeader &ih) {
      return (storage::bloom_check(ih.id_bloom, id));
    });
    *minResult = std::numeric_limits<dariadb::Time>::max();
    *maxResult = std::numeric_limits<dariadb::Time>::min();
    auto res = false;
    for (auto pname : pages) {
      auto p = Page::open(pname);
      dariadb::Time local_min, local_max;
      if (p->minMaxTime(id, &local_min, &local_max)) {
        *minResult = std::min(local_min, *minResult);
        *maxResult = std::max(local_max, *maxResult);
        res = true;
      }
      delete p;
    }
    return res;
  }

  class PageManagerCursor : public Cursor {
  public:
    bool is_end() const override { return _chunk_iterator == chunks.end(); }
    void readNext(Callback *cbk) override {
      if (!is_end()) {
        cbk->call(*_chunk_iterator);
        ++_chunk_iterator;
      }
    }
    void reset_pos() override { _chunk_iterator = chunks.begin(); }

    ChunksList chunks;
    ChunksList::iterator _chunk_iterator;
  };

  class AddCursorClbk : public Cursor::Callback {
  public:
    void call(dariadb::storage::Chunk_Ptr &ptr) {
      if (ptr != nullptr) {
        (*out)[ptr->info->first.id].push_back(ptr);
      }
    }

    ChunkMap *out;
  };

  ChunkLinkList chunksByIterval(const QueryInterval &query) {
    boost::shared_lock<boost::shared_mutex> lg(_locker);

    auto pred = [query](const IndexHeader &hdr) {
      auto interval_check(
          (hdr.minTime >= query.from && hdr.maxTime <= query.to) ||
          (utils::inInterval(query.from, query.to, hdr.minTime)) ||
          (utils::inInterval(query.from, query.to, hdr.maxTime)) ||
		  (utils::inInterval(hdr.minTime, hdr.maxTime, query.from)) ||
		  (utils::inInterval(hdr.minTime, hdr.maxTime, query.to)));
      if (interval_check) {
        for (auto id : query.ids) {
          if (storage::bloom_check(hdr.id_bloom, id)) {
            return true;
          }
        }
      }
      return false;
    };
    auto page_list =
        pages_by_filter(std::function<bool(const IndexHeader &)>(pred));

	ChunkLinkList result;
    for (auto pname : page_list) {
      Page *cand = Page::open(pname, true);

      auto sub_result=cand->chunksByIterval(query);
	  for (auto s:sub_result) {
		  s.page_name = pname;
		  result.push_back(s);
	  }
      delete cand;
    }

	return result;
  }

  Cursor_ptr  readLinks(const ChunkLinkList&links) {
	  boost::shared_lock<boost::shared_mutex> lg(_locker);

	  PageManagerCursor *raw_cursor = new PageManagerCursor;
	  ChunkMap chunks;

	  std::unique_ptr<AddCursorClbk> clbk{ new AddCursorClbk };
	  clbk->out = &chunks;

	  ChunkLinkList to_read;

	  for (auto l : links) {
		  if (to_read.empty()) {
			  to_read.push_back(l);
		  }else {
			  if (l.page_name == to_read.front().page_name) {
				  to_read.push_back(l);
			  }else {
				  auto p = Page::open(to_read.front().page_name);
				  p->readLinks(to_read)->readAll(clbk.get());
				  delete p;
				  to_read.clear();
				  to_read.push_back(l);
			  }
		  }
	  }
	  if (!to_read.empty()) {
		  auto p = Page::open(to_read.front().page_name);
		  p->readLinks(to_read)->readAll(clbk.get());
		  delete p;
		  to_read.clear();
	  }

	  /*for (auto kv : page2links) {
		  auto p = Page::open(kv.first);
		  p->readLinks(kv.second)->readAll(clbk.get());
		  delete p;
	  }*/

	  for (auto &kv : chunks) {
		  for (auto &ch : kv.second) {
			  raw_cursor->chunks.push_back(ch);
		  }
	  }
	  raw_cursor->reset_pos();
	  return Cursor_ptr{ raw_cursor };
  }
  std::list<std::string>
  pages_by_filter(std::function<bool(const IndexHeader &)> pred) {
    std::list<std::string> result;
    auto names = _manifest.page_list();
    for (auto n : names) {
      auto index_file_name = utils::fs::append_path(_param.path, n + "i");
      auto hdr = Page::readIndexHeader(index_file_name);
      if (pred(hdr)) {
        auto page_file_name = utils::fs::append_path(_param.path, n);
        result.push_back(page_file_name);
      }
    }
    return result;
  }

  ChunkLinkList chunksBeforeTimePoint(const QueryTimePoint &query) {
    boost::shared_lock<boost::shared_mutex> lg(_locker);

	ChunkLinkList result;

    auto pred = [query](const IndexHeader &hdr) {
		auto in_check =
			utils::inInterval(hdr.minTime, hdr.maxTime, query.time_point)
			|| (hdr.maxTime < query.time_point);
      if (in_check) {
        for (auto id : query.ids) {
          if (storage::bloom_check(hdr.id_bloom, id)) {
            return true;
          }
        }
      }
      return false;
    };
    auto page_list = pages_by_filter(std::function<bool(IndexHeader)>(pred));

    for (auto pname : page_list) {
      Page *pg = Page::open(pname, true);

      auto subres = pg->chunksBeforeTimePoint(query);
      for (auto s : subres) {
		  s.page_name = pname;
		  result.push_back(s);
      }
      delete pg;
    }

    return result;
  }

  dariadb::IdArray getIds() {
    boost::shared_lock<boost::shared_mutex> lg(_locker);

    auto pred = [](const IndexHeader &) { return true; };

    auto page_list = pages_by_filter(std::function<bool(IndexHeader)>(pred));
    dariadb::IdSet s;
    for (auto pname : page_list) {
      Page *pg = Page::open(pname, true);
      auto subres = pg->getIds();
      s.insert(subres.begin(), subres.end());
      delete pg;
    }

    return dariadb::IdArray(s.begin(), s.end());
  }

  size_t chunks_in_cur_page() const {
    if (_cur_page == nullptr) {
      return 0;
    }
    return _cur_page->header->addeded_chunks;
  }
  // PM
  size_t in_queue_size() const {
    return 0; /*return this->async_queue_size();*/
  }

  dariadb::Time minTime() {
	  boost::shared_lock<boost::shared_mutex> lg(_locker);

	  auto pred = [](const IndexHeader &) { return true; };

	  auto page_list = pages_by_filter(std::function<bool(IndexHeader)>(pred));

	  dariadb::Time res = std::numeric_limits<dariadb::Time>::max();
	  for (auto pname : page_list) {
		  auto ih = Page::readIndexHeader(pname + "i");
		  res = std::min(ih.minTime, res);
	  }

	  return res;
  }
  dariadb::Time maxTime() {
	  boost::shared_lock<boost::shared_mutex> lg(_locker);

	  auto pred = [](const IndexHeader &) { return true; };

	  auto page_list = pages_by_filter(std::function<bool(IndexHeader)>(pred));

	  dariadb::Time res = std::numeric_limits<dariadb::Time>::max();
	  for (auto pname : page_list) {
		  auto ih = Page::readIndexHeader(pname + "i");
		  res = std::max(ih.maxTime, res);
	  }

	  return res;
  }

  append_result append(const Meas &value) {
    boost::upgrade_lock<boost::shared_mutex> lg(_locker);

    while (true) {
      auto cur_page = this->get_cur_page();
      if (update_id) {
        //_cur_page->header->max_chunk_id= last_id;
        update_id = false;
      }
      auto res = cur_page->append(value);
      if (res.writed != 1) {
        last_id = _cur_page->header->max_chunk_id;
        update_id = true;
        delete _cur_page;
        _cur_page = nullptr;
      } else {
        return res;
      }
    }
  }

protected:
  Page *_cur_page;
  PageManager::Params _param;
  Manifest _manifest;
  boost::shared_mutex _locker;

  uint64_t last_id;
  bool update_id;
};

PageManager::PageManager(const PageManager::Params &param)
    : impl(new PageManager::Private{param}) {}

PageManager::~PageManager() {}

void PageManager::start(const PageManager::Params &param) {
  if (PageManager::_instance == nullptr) {
    PageManager::_instance = new PageManager(param);
  }
}

void PageManager::stop() {
  if (_instance != nullptr) {
    delete PageManager::_instance;
    _instance = nullptr;
  }
}

void PageManager::flush() {
  this->impl->flush();
}

PageManager *PageManager::instance() {
  return _instance;
}
// PM
// bool PageManager::append(const Chunk_Ptr &c) {
//  return impl->append(c);
//}
//
// bool PageManager::append(const ChunksList &c) {
//  return impl->append(c);
//}

// Cursor_ptr PageManager::get_chunks(const dariadb::IdArray&ids, dariadb::Time
// from, dariadb::Time to, dariadb::Flag flag) {
//    return impl->get_chunks(ids, from, to, flag);
//}
// ChunkContainer
bool PageManager::minMaxTime(dariadb::Id id, dariadb::Time *minResult,
                             dariadb::Time *maxResult) {
  return impl->minMaxTime(id, minResult, maxResult);
}

dariadb::storage::ChunkLinkList
PageManager::chunksByIterval(const QueryInterval &query) {
  return impl->chunksByIterval(query);
}

dariadb::storage::ChunkLinkList
PageManager::chunksBeforeTimePoint(const QueryTimePoint &q) {
  return impl->chunksBeforeTimePoint(q);
}

dariadb::storage::Cursor_ptr
PageManager::readLinks(const ChunkLinkList&links) {
	return impl->readLinks(links);
}

dariadb::IdArray PageManager::getIds() {
  return impl->getIds();
}

size_t PageManager::in_queue_size() const {
  return impl->in_queue_size();
}

dariadb::Time PageManager::minTime() {
  return impl->minTime();
}

dariadb::Time PageManager::maxTime() {
  return impl->maxTime();
}

dariadb::append_result
dariadb::storage::PageManager::append(const Meas &value) {
  return impl->append(value);
}
<commit_msg>PM: dont open openned page on read.<commit_after>#include "page_manager.h"
#include "../utils/asyncworker.h"
#include "../utils/fs.h"
#include "../utils/locker.h"
#include "../utils/utils.h"
#include "manifest.h"
#include "page.h"

#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <condition_variable>
#include <cstring>
#include <functional>
#include <memory>
#include <queue>
#include <thread>

const std::string MANIFEST_FILE_NAME = "Manifest";

using namespace dariadb::storage;
dariadb::storage::PageManager *PageManager::_instance = nullptr;
// PM
class PageManager::Private /*:public dariadb::utils::AsyncWorker<Chunk_Ptr>*/ {
public:
  Private(const PageManager::Params &param)
      : _cur_page(nullptr), _param(param),
        _manifest(utils::fs::append_path(param.path, MANIFEST_FILE_NAME)) {
    update_id = false;
    last_id = 0;

    _cur_page = open_last_openned();
    /*this->start_async();*/
  }

  Page *open_last_openned() {
    if (!utils::fs::path_exists(_param.path)) {
      return nullptr;
    }
    auto pages = _manifest.page_list();

    for (auto n : pages) {
      auto file_name = utils::fs::append_path(_param.path, n);
      auto hdr = Page::readHeader(file_name);
      if (!hdr.is_full) {
        auto res = Page::open(file_name);
        update_id = false;
        return res;
      } else {
        last_id = std::max(last_id, hdr.max_chunk_id);
        update_id = true;
      }
    }
    return nullptr;
  }

  ~Private() {
    /* this->stop_async();*/

    if (_cur_page != nullptr) {
      delete _cur_page;
      _cur_page = nullptr;
    }
  }

  uint64_t calc_page_size() const {
    auto sz_info = _param.chunk_per_storage * sizeof(ChunkIndexInfo);
    auto sz_buffers = _param.chunk_per_storage * _param.chunk_size;
    return sizeof(PageHeader) + sz_buffers + sz_info;
  }

  Page *create_page() {
    if (!dariadb::utils::fs::path_exists(_param.path)) {
      dariadb::utils::fs::mkdir(_param.path);
    }

    Page *res = nullptr; // open_last_openned();

    // if (res == nullptr) {
    std::string page_name = utils::fs::random_file_name(".page");
    std::string file_name =
        dariadb::utils::fs::append_path(_param.path, page_name);
    auto sz = calc_page_size();
    res = Page::create(file_name, sz, _param.chunk_per_storage,
                       _param.chunk_size);
    _manifest.page_append(page_name);
    if (update_id) {
      res->header->max_chunk_id = last_id;
    }
    //}

    return res;
  }
  // PM
  void flush() { /*this->flush_async();*/
  }
  // void call_async(const Chunk_Ptr &ch) override { /*write_to_page(ch);*/ }

  Page *get_cur_page() {
    if (_cur_page == nullptr) {
      _cur_page = create_page();
    }
    return _cur_page;
  }

  bool minMaxTime(dariadb::Id id, dariadb::Time *minResult,
                  dariadb::Time *maxResult) {
    boost::shared_lock<boost::shared_mutex> lg(_locker);

    auto pages = pages_by_filter([id](const IndexHeader &ih) {
      return (storage::bloom_check(ih.id_bloom, id));
    });
    *minResult = std::numeric_limits<dariadb::Time>::max();
    *maxResult = std::numeric_limits<dariadb::Time>::min();
    auto res = false;
    for (auto pname : pages) {
        Page *pg = nullptr;
        bool close_page=true;
        if(_cur_page!=nullptr && pname==_cur_page->filename){
                pg=_cur_page;
                close_page=false;

        }else{
            pg=Page::open(pname, true);
        }
      dariadb::Time local_min, local_max;
      if (pg->minMaxTime(id, &local_min, &local_max)) {
        *minResult = std::min(local_min, *minResult);
        *maxResult = std::max(local_max, *maxResult);
        res = true;
      }
      if(close_page){
          delete pg;
      }
    }
    return res;
  }

  class PageManagerCursor : public Cursor {
  public:
    bool is_end() const override { return _chunk_iterator == chunks.end(); }
    void readNext(Callback *cbk) override {
      if (!is_end()) {
        cbk->call(*_chunk_iterator);
        ++_chunk_iterator;
      }
    }
    void reset_pos() override { _chunk_iterator = chunks.begin(); }

    ChunksList chunks;
    ChunksList::iterator _chunk_iterator;
  };

  class AddCursorClbk : public Cursor::Callback {
  public:
    void call(dariadb::storage::Chunk_Ptr &ptr) {
      if (ptr != nullptr) {
        (*out)[ptr->info->first.id].push_back(ptr);
      }
    }

    ChunkMap *out;
  };

  ChunkLinkList chunksByIterval(const QueryInterval &query) {
    boost::shared_lock<boost::shared_mutex> lg(_locker);

    auto pred = [query](const IndexHeader &hdr) {
      auto interval_check(
          (hdr.minTime >= query.from && hdr.maxTime <= query.to) ||
          (utils::inInterval(query.from, query.to, hdr.minTime)) ||
          (utils::inInterval(query.from, query.to, hdr.maxTime)) ||
		  (utils::inInterval(hdr.minTime, hdr.maxTime, query.from)) ||
		  (utils::inInterval(hdr.minTime, hdr.maxTime, query.to)));
      if (interval_check) {
        for (auto id : query.ids) {
          if (storage::bloom_check(hdr.id_bloom, id)) {
            return true;
          }
        }
      }
      return false;
    };
    auto page_list =
        pages_by_filter(std::function<bool(const IndexHeader &)>(pred));

	ChunkLinkList result;
    for (auto pname : page_list) {
        Page *pg = nullptr;
        bool close_page=true;
        if(_cur_page!=nullptr && pname==_cur_page->filename){
                pg=_cur_page;
                close_page=false;

        }else{
            pg=Page::open(pname, true);
        }

      auto sub_result=pg->chunksByIterval(query);
	  for (auto s:sub_result) {
		  s.page_name = pname;
		  result.push_back(s);
	  }
      if(close_page){
          delete pg;
      }
    }

	return result;
  }

  Cursor_ptr  readLinks(const ChunkLinkList&links) {
	  boost::shared_lock<boost::shared_mutex> lg(_locker);

	  PageManagerCursor *raw_cursor = new PageManagerCursor;
	  ChunkMap chunks;

	  std::unique_ptr<AddCursorClbk> clbk{ new AddCursorClbk };
	  clbk->out = &chunks;

	  ChunkLinkList to_read;

	  for (auto l : links) {
		  if (to_read.empty()) {
			  to_read.push_back(l);
		  }else {
			  if (l.page_name == to_read.front().page_name) {
				  to_read.push_back(l);
			  }else {
                  auto pname=to_read.front().page_name;
                  Page *pg = nullptr;
                  bool close_page=true;
                  if(_cur_page!=nullptr && pname==_cur_page->filename){
                          pg=_cur_page;
                          close_page=false;

                  }else{
                      pg=Page::open(pname, true);
                  }

                  pg->readLinks(to_read)->readAll(clbk.get());
                  if(close_page){
                      delete pg;
                  }
				  to_read.clear();
				  to_read.push_back(l);
			  }
		  }
	  }
	  if (!to_read.empty()) {
          auto pname=to_read.front().page_name;
          Page *pg = nullptr;
          bool close_page=true;
          if(_cur_page!=nullptr && pname==_cur_page->filename){
                  pg=_cur_page;
                  close_page=false;
          }else{
              pg=Page::open(pname, true);
          }

          pg->readLinks(to_read)->readAll(clbk.get());
          if(close_page){
              delete pg;
          }
		  to_read.clear();
	  }

	  /*for (auto kv : page2links) {
		  auto p = Page::open(kv.first);
		  p->readLinks(kv.second)->readAll(clbk.get());
		  delete p;
	  }*/

	  for (auto &kv : chunks) {
		  for (auto &ch : kv.second) {
			  raw_cursor->chunks.push_back(ch);
		  }
	  }
	  raw_cursor->reset_pos();
	  return Cursor_ptr{ raw_cursor };
  }
  std::list<std::string>
  pages_by_filter(std::function<bool(const IndexHeader &)> pred) {
    std::list<std::string> result;
    auto names = _manifest.page_list();
    for (auto n : names) {
      auto index_file_name = utils::fs::append_path(_param.path, n + "i");
      auto hdr = Page::readIndexHeader(index_file_name);
      if (pred(hdr)) {
        auto page_file_name = utils::fs::append_path(_param.path, n);
        result.push_back(page_file_name);
      }
    }
    return result;
  }

  ChunkLinkList chunksBeforeTimePoint(const QueryTimePoint &query) {
    boost::shared_lock<boost::shared_mutex> lg(_locker);

	ChunkLinkList result;

    auto pred = [query](const IndexHeader &hdr) {
		auto in_check =
			utils::inInterval(hdr.minTime, hdr.maxTime, query.time_point)
			|| (hdr.maxTime < query.time_point);
      if (in_check) {
        for (auto id : query.ids) {
          if (storage::bloom_check(hdr.id_bloom, id)) {
            return true;
          }
        }
      }
      return false;
    };
    auto page_list = pages_by_filter(std::function<bool(IndexHeader)>(pred));

    for (auto pname : page_list) {
      Page *pg = nullptr;
      bool close_page=true;
      if(_cur_page!=nullptr && pname==_cur_page->filename){
              pg=_cur_page;
              close_page=false;
      }else{
          pg=Page::open(pname, true);
      }

      auto subres = pg->chunksBeforeTimePoint(query);
      for (auto s : subres) {
		  s.page_name = pname;
		  result.push_back(s);
      }
      if(close_page){
          delete pg;
      }
    }

    return result;
  }

  dariadb::IdArray getIds() {
    boost::shared_lock<boost::shared_mutex> lg(_locker);

    auto pred = [](const IndexHeader &) { return true; };

    auto page_list = pages_by_filter(std::function<bool(IndexHeader)>(pred));
    dariadb::IdSet s;
    for (auto pname : page_list) {
        Page *pg = nullptr;
        bool close_page=true;
        if(_cur_page!=nullptr && pname==_cur_page->filename){
                pg=_cur_page;
                close_page=false;
        }else{
            pg=Page::open(pname, true);
        }
        auto subres = pg->getIds();
        s.insert(subres.begin(), subres.end());
        if(close_page){
            delete pg;
        }
    }

    return dariadb::IdArray(s.begin(), s.end());
  }

  size_t chunks_in_cur_page() const {
    if (_cur_page == nullptr) {
      return 0;
    }
    return _cur_page->header->addeded_chunks;
  }
  // PM
  size_t in_queue_size() const {
    return 0; /*return this->async_queue_size();*/
  }

  dariadb::Time minTime() {
	  boost::shared_lock<boost::shared_mutex> lg(_locker);

	  auto pred = [](const IndexHeader &) { return true; };

	  auto page_list = pages_by_filter(std::function<bool(IndexHeader)>(pred));

	  dariadb::Time res = std::numeric_limits<dariadb::Time>::max();
	  for (auto pname : page_list) {
		  auto ih = Page::readIndexHeader(pname + "i");
		  res = std::min(ih.minTime, res);
	  }

	  return res;
  }
  dariadb::Time maxTime() {
	  boost::shared_lock<boost::shared_mutex> lg(_locker);

	  auto pred = [](const IndexHeader &) { return true; };

	  auto page_list = pages_by_filter(std::function<bool(IndexHeader)>(pred));

	  dariadb::Time res = std::numeric_limits<dariadb::Time>::max();
	  for (auto pname : page_list) {
		  auto ih = Page::readIndexHeader(pname + "i");
		  res = std::max(ih.maxTime, res);
	  }

	  return res;
  }

  append_result append(const Meas &value) {
    boost::upgrade_lock<boost::shared_mutex> lg(_locker);

    while (true) {
      auto cur_page = this->get_cur_page();
      if (update_id) {
        //_cur_page->header->max_chunk_id= last_id;
        update_id = false;
      }
      auto res = cur_page->append(value);
      if (res.writed != 1) {
        last_id = _cur_page->header->max_chunk_id;
        update_id = true;
        delete _cur_page;
        _cur_page = nullptr;
      } else {
        return res;
      }
    }
  }

protected:
  Page *_cur_page;
  PageManager::Params _param;
  Manifest _manifest;
  boost::shared_mutex _locker;

  uint64_t last_id;
  bool update_id;
};

PageManager::PageManager(const PageManager::Params &param)
    : impl(new PageManager::Private{param}) {}

PageManager::~PageManager() {}

void PageManager::start(const PageManager::Params &param) {
  if (PageManager::_instance == nullptr) {
    PageManager::_instance = new PageManager(param);
  }
}

void PageManager::stop() {
  if (_instance != nullptr) {
    delete PageManager::_instance;
    _instance = nullptr;
  }
}

void PageManager::flush() {
  this->impl->flush();
}

PageManager *PageManager::instance() {
  return _instance;
}
// PM
// bool PageManager::append(const Chunk_Ptr &c) {
//  return impl->append(c);
//}
//
// bool PageManager::append(const ChunksList &c) {
//  return impl->append(c);
//}

// Cursor_ptr PageManager::get_chunks(const dariadb::IdArray&ids, dariadb::Time
// from, dariadb::Time to, dariadb::Flag flag) {
//    return impl->get_chunks(ids, from, to, flag);
//}
// ChunkContainer
bool PageManager::minMaxTime(dariadb::Id id, dariadb::Time *minResult,
                             dariadb::Time *maxResult) {
  return impl->minMaxTime(id, minResult, maxResult);
}

dariadb::storage::ChunkLinkList
PageManager::chunksByIterval(const QueryInterval &query) {
  return impl->chunksByIterval(query);
}

dariadb::storage::ChunkLinkList
PageManager::chunksBeforeTimePoint(const QueryTimePoint &q) {
  return impl->chunksBeforeTimePoint(q);
}

dariadb::storage::Cursor_ptr
PageManager::readLinks(const ChunkLinkList&links) {
	return impl->readLinks(links);
}

dariadb::IdArray PageManager::getIds() {
  return impl->getIds();
}

size_t PageManager::in_queue_size() const {
  return impl->in_queue_size();
}

dariadb::Time PageManager::minTime() {
  return impl->minTime();
}

dariadb::Time PageManager::maxTime() {
  return impl->maxTime();
}

dariadb::append_result
dariadb::storage::PageManager::append(const Meas &value) {
  return impl->append(value);
}
<|endoftext|>


<commit_before>/*-
 * Copyright (c) 2009-2010 Benjamin Close <Benjamin.Close@clearchain.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include "ARToolKitPlusTracker.h"
#include <assert.h>
#include <ARToolKitPlus/CameraImpl.h>
#include <ARToolKitPlus/CameraAdvImpl.h>

using namespace ARToolKitPlus;

namespace wcl {

ARToolKitPlusTracker::ARToolKitPlusTracker( const unsigned imarkerWidth, const int thresholdValue,
					    const unsigned iscreenWidth, const unsigned iscreenHeight,
					    const float inearplane, const float ifarplane):
    markerWidth(imarkerWidth), scale(CM), cameraFormat(Camera::RGB8),
    nearplane(inearplane), farplane(ifarplane),inited(false)
{

    assert( imarkerWidth != 0 && "Using ARToolKitPlus with a marker width of zero doesn't make sense");

    // create a tracker that does:
    //  - 6x6 sized marker images (in bch pixel) - we hard code this as 4096 images is huge
    //  - samples at a maximum of 6x6 -??? Seems to relate to image division maximum
    //  - can load a maximum of 0 pattern - not required as we use BCH patterns
    //  - can detect a maximum of imaxMarkserPerImage patterns in one image
    this->tracker=
	new ARToolKitPlus::TrackerSingleMarkerImpl<6,6,6, 0, WCL_ARTOOLKITPLUSTRACKER_MARKER_DETECTION_COUNT>(iscreenWidth, iscreenHeight);

    this->tracker->setPatternWidth(imarkerWidth);

    // Use LUT lookups to speed up calculations, these only works with images up to 1024x1024
    if( iscreenWidth < 1024 && iscreenHeight < 1024 )
	this->tracker->setUndistortionMode(ARToolKitPlus::UNDIST_LUT);

    // Use binary encoded markers
    this->tracker->setMarkerMode(ARToolKitPlus::MARKER_ID_BCH);

    // We use BCH images which have a thinner border
    this->tracker->setBorderWidth (0.125f);

    // Set the threshold to either a user value or auto by default
    this->setThreshold( thresholdValue );

    // Use the updated pose estimator (Robust Pose Estimation From a Planar Target)
    this->tracker->setPoseEstimator(POSE_ESTIMATOR_RPP);

    // Create 4096 base markers as we use BCH, and also populate the map
    for(unsigned i=0; i < 4096; i++ ){
	ARToolKitPlusTrackedObject *o = new ARToolKitPlusTrackedObject(imarkerWidth, i);
	this->objects.push_back(o);

	this->mapping[i] = o;
    }
}

ARToolKitPlusTracker::~ARToolKitPlusTracker()
{

    // ARToolkitPlus deletes the last camera assigned hence we don't
    // need to call: delete this->c_ptr as it's already done and
    // would cause a SIGSEGV if we try it
    delete this->tracker;

    for(std::vector<ARToolKitPlusTrackedObject *>::iterator it = this->objects.begin();
	it != this->objects.end();
	++it ){
	ARToolKitPlusTrackedObject *object= *it;
	delete object;
    }
}

void ARToolKitPlusTracker::setCamera(Camera *camera)
{
    assert( camera != NULL && "You Can't specifiy NULL for the camera");
    //assert( camera->hasDistortionMatrix() != false && "You must have a valid distortion matrix for the camera before ARToolKitPlusTracker will work");

    this->camera = camera;

    ARToolKitPlus::PIXEL_FORMAT format;

    // Set the format based on what the camera is using
    switch (this->camera->getImageFormat()){
	case Camera::RGB8:
            format=ARToolKitPlus::PIXEL_FORMAT_RGB;
	    this->cameraFormat = Camera::RGB8;
            break;
	case Camera::BGR8:
            format=ARToolKitPlus::PIXEL_FORMAT_BGR;
	    this->cameraFormat = Camera::BGR8;
	case Camera::MONO8:
	    format=ARToolKitPlus::PIXEL_FORMAT_LUM;
	    this->cameraFormat = Camera::MONO8;
            break;
        default:
	case Camera::MJPEG:
	case Camera::YUYV422:
            printf("ARToolKitPlusTracker:SetCamera: Unsupported Camera Image Format converting to RGB8 via software\n");
	    this->cameraFormat = Camera::RGB8;
            format=ARToolKitPlus::PIXEL_FORMAT_RGB;
	    break;
    }

    // Create a new ARToolkit Camera to
    // init the tracker, note ARToolKitPlus will remove
    // delete the last camera hence we never need to free this camera
    ARToolKitPlus::Camera *c_ptr = new ARToolKitPlus::CameraImpl;
    c_ptr->xsize=this->camera->getFormatWidth();
    c_ptr->ysize=this->camera->getFormatHeight();
    Camera::CameraParameters d = this->getParameters();
    c_ptr->mat[0][0]=d.intrinsicMatrix[0][0];
    c_ptr->mat[0][1]=d.intrinsicMatrix[0][1];
    c_ptr->mat[0][2]=d.intrinsicMatrix[0][2];
    c_ptr->mat[1][0]=d.intrinsicMatrix[1][0];
    c_ptr->mat[1][1]=d.intrinsicMatrix[1][1];
    c_ptr->mat[1][2]=d.intrinsicMatrix[1][2];
    c_ptr->mat[2][0]=d.intrinsicMatrix[2][0];
    c_ptr->mat[2][1]=d.intrinsicMatrix[2][1];
    c_ptr->mat[2][2]=d.intrinsicMatrix[2][2];
    c_ptr->mat[3][0]=d.intrinsicMatrix[3][0];
    c_ptr->mat[3][1]=d.intrinsicMatrix[3][1];
    c_ptr->mat[3][2]=d.intrinsicMatrix[3][2];
    c_ptr->dist_factor[0]=d.distortion[0];
    c_ptr->dist_factor[1]=d.distortion[1];
    c_ptr->dist_factor[2]=d.distortion[2];
    c_ptr->dist_factor[3]=d.distortion[3];

    this->tracker->setPixelFormat(format);
    this->tracker->init(NULL, this->nearplane, this->farplane);
    this->tracker->setCamera(c_ptr, this->nearplane, this->farplane);
    this->inited = true;
}

void ARToolKitPlusTracker::update()
{
    int i=0;
    ARMarkerInfo *markers;
    ARFloat conv[3][4];
    ARFloat center[2]={0.0,0.0};// XXX Hard coded as per ARToolKitPlus::TrackerSingleMarkerImpl.cxx

    assert( this->inited && "ARToolKitPlusTracker:update() : The tracker has not yet been inited, please call setCamera First" );

    this->bestMarker=this->tracker->calc(this->camera->getFrame(this->cameraFormat), -1, true, &markers, &this->markersFound);
    this->confidence = (float)tracker->getConfidence();

    // set all markers to not visable
    for(std::vector<ARToolKitPlusTrackedObject *>::iterator it = this->objects.begin();
	it != this->objects.end();
	++it ){
	ARToolKitPlusTrackedObject *marker=*it;
	marker->setVisible(false);
    }

    // Update the found markers
    while( i < this->markersFound ){
	SMatrix m(4);
	m.storeIdentity();
	this->tracker->executeSingleMarkerPoseEstimator(&markers[i],
							center,
							this->markerWidth,
							conv );

	//
	// ARToolkit may return marker ids not in the map in the case of
	// invalid detection. We hence search here for a valid id
	//
	std::map<unsigned, ARToolKitPlusTrackedObject *>::iterator it = this->mapping.find(markers[i].id);
	if( it != this->mapping.end()){
	    ARToolKitPlusTrackedObject *marker = it->second;
	    if( marker != NULL ){

		for(unsigned row=0; row < 3; row++ )
		    for(unsigned c =0; c < 4; c++)
			m[row][c]=conv[row][c];

		//
		// Apply scaling if required
		//
		switch(this->scale)
		{
		    case MM:
			    m[0][3]*=10.0;
			    m[1][3]*=10.0;
			    m[2][3]*=10.0;
			    break;
		    case CM:
			    break; // No Scaling Needed, ARToolKit Default
		    case INCHES:
			    m[0][3]/=25.4;
			    m[1][3]/=25.4;
			    m[2][3]/=25.4;
			    break;
		}

		marker->setTransform(m);
		marker->setVisible(true);
		marker->setConfidence(markers[i].cf);
	    }
	}
	i++;
    }
}

TrackedObject* ARToolKitPlusTracker::getObject(const std::string name)
{
    for(std::vector<ARToolKitPlusTrackedObject *>::iterator it=this->objects.begin();
	it != this->objects.end();
	++it )
    {
	ARToolKitPlusTrackedObject *temp = *it;
	if(temp->getName()==name)
	    return temp;
    }

    return NULL;
}

std::vector<TrackedObject *> ARToolKitPlusTracker::getAllObjects()
{
    std::vector<TrackedObject *> v;
    for(std::vector<ARToolKitPlusTrackedObject *>::iterator it =
	this->objects.begin();
	it!=this->objects.end();
	++it)
	if( (*it)->isVisible())
	    v.push_back(*it);
    return v;
}

void ARToolKitPlusTracker::setUnits(Units u)
{
    this->scale = u;
}

void ARToolKitPlusTracker::setThreshold(const int value )
{
    if( value < 0 )
	this->tracker->activateAutoThreshold(true);
    else {
	this->tracker->activateAutoThreshold(false);
	this->tracker->setThreshold(value);
    }
}

void ARToolKitPlusTracker::toString()
{
    const char* description = this->tracker->getDescription();
    printf("ARToolKitPlus compile-time information:\n%s\n\n", description);
    printf("Thresholding: %s, current value %d\n",
	   this->tracker->isAutoThresholdActivated() ? "AUTO": "MANUAL",
	   this->tracker->getThreshold());
    printf("%d Markers found, %d is the id of best marker with a %f confidence\n",
	   this->markersFound,
	   this->bestMarker,
	   this->confidence);

    std::vector<TrackedObject *> allobjects = this->getAllObjects();
    for(std::vector<TrackedObject *>::iterator it = allobjects.begin();
	it != allobjects.end();
	++it ){
	ARToolKitPlusTrackedObject *marker = (ARToolKitPlusTrackedObject *)*it;
	printf("%5d : Confidence %f\n", marker->getID(), marker->getConfidence());
    }
    if( this->markersFound > 0 ){
	printf("Best Marker Matrix:\n");
	for(int i=0; i<16; i++)
	    printf("%.4f  %s", tracker->getModelViewMatrix()[i], (i%4==3)?"\n  " : "");
    }
}

/**
 * Get the projection matrix ARToolkit is using
 */
SMatrix ARToolKitPlusTracker::getProjectionMatrix()
{
    SMatrix m(4);
    const ARFloat *f = this->tracker->getProjectionMatrix();
    int i=0;
    for( int r=0; r<4;r++ ){
	for ( int c=0; c<4; c++)
	    m[c][r]=f[i++];

    }

    return m;
}

/**
 * Get the model view matrix of the best marker
 *
 * @return The model view matrix of the best marker
 */
SMatrix ARToolKitPlusTracker::getModelViewMatrix()
{
    SMatrix m(4);
    const ARFloat *f = this->tracker->getModelViewMatrix();
    int i=0;
    for( int r=0; r<4;r++ ){
	for ( int c=0; c<4; c++)
	    m[c][r]=f[i++];

    }

    return m;
};

Camera::CameraParameters ARToolKitPlusTracker::getParameters()
{
    if( this->camera->hasParameters())
	return this->camera->getParameters();

    printf("ARToolKitPlusTracker::getDistortion: There is no distortion matrix available for your camera\n"
	   "                      using a default, things may go strange near the edge of the image\n");

    Camera::CameraParameters d;

    d.intrinsicMatrix[0][0]=406.040405;
    d.intrinsicMatrix[0][1]=0.;
    d.intrinsicMatrix[0][2]=154.0;
    d.intrinsicMatrix[0][3]=0.;
    d.intrinsicMatrix[1][0]=0.;
    d.intrinsicMatrix[1][1]=404.388489;
    d.intrinsicMatrix[1][2]=115;
    d.intrinsicMatrix[1][3]=0;
    d.intrinsicMatrix[2][0]=0.;
    d.intrinsicMatrix[2][1]=0.;
    d.intrinsicMatrix[2][2]=1.;
    d.intrinsicMatrix[2][3]=0.;
    d.distortion[0]=159.;
    d.distortion[1]=139.;
    d.distortion[2]=-84.9000015;
    d.distortion[3]=0.979329705;

    return d;
}

}; // namespace wcl
<commit_msg>Switch to ARToolkitPlus's advanced camera model.<commit_after>/*-
 * Copyright (c) 2009-2010 Benjamin Close <Benjamin.Close@clearchain.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include "ARToolKitPlusTracker.h"
#include <assert.h>
#include <ARToolKitPlus/CameraImpl.h>
#include <ARToolKitPlus/CameraAdvImpl.h>

using namespace ARToolKitPlus;

namespace wcl {

ARToolKitPlusTracker::ARToolKitPlusTracker( const unsigned imarkerWidth, const int thresholdValue,
					    const unsigned iscreenWidth, const unsigned iscreenHeight,
					    const float inearplane, const float ifarplane):
    markerWidth(imarkerWidth), scale(CM), cameraFormat(Camera::RGB8),
    nearplane(inearplane), farplane(ifarplane),inited(false)
{

    assert( imarkerWidth != 0 && "Using ARToolKitPlus with a marker width of zero doesn't make sense");

    // create a tracker that does:
    //  - 6x6 sized marker images (in bch pixel) - we hard code this as 4096 images is huge
    //  - samples at a maximum of 6x6 -??? Seems to relate to image division maximum
    //  - can load a maximum of 0 pattern - not required as we use BCH patterns
    //  - can detect a maximum of imaxMarkserPerImage patterns in one image
    this->tracker=
	new ARToolKitPlus::TrackerSingleMarkerImpl<6,6,6, 0, WCL_ARTOOLKITPLUSTRACKER_MARKER_DETECTION_COUNT>(iscreenWidth, iscreenHeight);

    this->tracker->setPatternWidth(imarkerWidth);

    // Use LUT lookups to speed up calculations, these only works with images up to 1024x1024
    if( iscreenWidth < 1024 && iscreenHeight < 1024 )
	this->tracker->setUndistortionMode(ARToolKitPlus::UNDIST_LUT);

    // Use binary encoded markers
    this->tracker->setMarkerMode(ARToolKitPlus::MARKER_ID_BCH);

    // We use BCH images which have a thinner border
    this->tracker->setBorderWidth (0.125f);

    // Set the threshold to either a user value or auto by default
    this->setThreshold( thresholdValue );

    // Use the updated pose estimator (Robust Pose Estimation From a Planar Target)
    this->tracker->setPoseEstimator(POSE_ESTIMATOR_RPP);

    // Create 4096 base markers as we use BCH, and also populate the map
    for(unsigned i=0; i < 4096; i++ ){
	ARToolKitPlusTrackedObject *o = new ARToolKitPlusTrackedObject(imarkerWidth, i);
	this->objects.push_back(o);

	this->mapping[i] = o;
    }
}

ARToolKitPlusTracker::~ARToolKitPlusTracker()
{

    // ARToolkitPlus deletes the last camera assigned hence we don't
    // need to call: delete this->c_ptr as it's already done and
    // would cause a SIGSEGV if we try it
    delete this->tracker;

    for(std::vector<ARToolKitPlusTrackedObject *>::iterator it = this->objects.begin();
	it != this->objects.end();
	++it ){
	ARToolKitPlusTrackedObject *object= *it;
	delete object;
    }
}

void ARToolKitPlusTracker::setCamera(Camera *camera)
{
    assert( camera != NULL && "You Can't specifiy NULL for the camera");
    //assert( camera->hasDistortionMatrix() != false && "You must have a valid distortion matrix for the camera before ARToolKitPlusTracker will work");

    this->camera = camera;

    ARToolKitPlus::PIXEL_FORMAT format;

    // Set the format based on what the camera is using
    switch (this->camera->getImageFormat()){
	case Camera::RGB8:
            format=ARToolKitPlus::PIXEL_FORMAT_RGB;
	    this->cameraFormat = Camera::RGB8;
            break;
	case Camera::BGR8:
            format=ARToolKitPlus::PIXEL_FORMAT_BGR;
	    this->cameraFormat = Camera::BGR8;
	case Camera::MONO8:
	    format=ARToolKitPlus::PIXEL_FORMAT_LUM;
	    this->cameraFormat = Camera::MONO8;
            break;
        default:
	case Camera::MJPEG:
	case Camera::YUYV422:
            printf("ARToolKitPlusTracker:SetCamera: Unsupported Camera Image Format converting to RGB8 via software\n");
	    this->cameraFormat = Camera::RGB8;
            format=ARToolKitPlus::PIXEL_FORMAT_RGB;
	    break;
    }

    // Create a new ARToolkit Camera to
    // init the tracker, note ARToolKitPlus will remove
    // delete the last camera hence we never need to free this camera
    ARToolKitPlus::Camera *c_ptr = new ARToolKitPlus::CameraAdvImpl;
    c_ptr->xsize=this->camera->getFormatWidth();
    c_ptr->ysize=this->camera->getFormatHeight();
    Camera::CameraParameters d = this->getParameters();
    c_ptr->mat[0][0]=d.intrinsicMatrix[0][0];
    c_ptr->mat[0][1]=d.intrinsicMatrix[0][1];
    c_ptr->mat[0][2]=d.intrinsicMatrix[0][2];
    c_ptr->mat[1][0]=d.intrinsicMatrix[1][0];
    c_ptr->mat[1][1]=d.intrinsicMatrix[1][1];
    c_ptr->mat[1][2]=d.intrinsicMatrix[1][2];
    c_ptr->mat[2][0]=d.intrinsicMatrix[2][0];
    c_ptr->mat[2][1]=d.intrinsicMatrix[2][1];
    c_ptr->mat[2][2]=d.intrinsicMatrix[2][2];
    c_ptr->mat[3][0]=d.intrinsicMatrix[3][0];
    c_ptr->mat[3][1]=d.intrinsicMatrix[3][1];
    c_ptr->mat[3][2]=d.intrinsicMatrix[3][2];
    c_ptr->dist_factor[0]=d.distortion[0];
    c_ptr->dist_factor[1]=d.distortion[1];
    c_ptr->dist_factor[2]=d.distortion[2];
    c_ptr->dist_factor[3]=d.distortion[3];
    c_ptr->dist_factor[4]=0;

    this->tracker->setPixelFormat(format);
    this->tracker->init(NULL, this->nearplane, this->farplane);
    this->tracker->setCamera(c_ptr, this->nearplane, this->farplane);
    this->inited = true;
}

void ARToolKitPlusTracker::update()
{
    int i=0;
    ARMarkerInfo *markers;
    ARFloat conv[3][4];
    ARFloat center[2]={0.0,0.0};// XXX Hard coded as per ARToolKitPlus::TrackerSingleMarkerImpl.cxx

    assert( this->inited && "ARToolKitPlusTracker:update() : The tracker has not yet been inited, please call setCamera First" );

    this->bestMarker=this->tracker->calc(this->camera->getFrame(this->cameraFormat), -1, true, &markers, &this->markersFound);
    this->confidence = (float)tracker->getConfidence();

    // set all markers to not visable
    for(std::vector<ARToolKitPlusTrackedObject *>::iterator it = this->objects.begin();
	it != this->objects.end();
	++it ){
	ARToolKitPlusTrackedObject *marker=*it;
	marker->setVisible(false);
    }

    // Update the found markers
    while( i < this->markersFound ){
	SMatrix m(4);
	m.storeIdentity();
	this->tracker->executeSingleMarkerPoseEstimator(&markers[i],
							center,
							this->markerWidth,
							conv );

	//
	// ARToolkit may return marker ids not in the map in the case of
	// invalid detection. We hence search here for a valid id
	//
	std::map<unsigned, ARToolKitPlusTrackedObject *>::iterator it = this->mapping.find(markers[i].id);
	if( it != this->mapping.end()){
	    ARToolKitPlusTrackedObject *marker = it->second;
	    if( marker != NULL ){

		for(unsigned row=0; row < 3; row++ )
		    for(unsigned c =0; c < 4; c++)
			m[row][c]=conv[row][c];

		//
		// Apply scaling if required
		//
		switch(this->scale)
		{
		    case MM:
			    m[0][3]*=10.0;
			    m[1][3]*=10.0;
			    m[2][3]*=10.0;
			    break;
		    case CM:
			    break; // No Scaling Needed, ARToolKit Default
		    case INCHES:
			    m[0][3]/=25.4;
			    m[1][3]/=25.4;
			    m[2][3]/=25.4;
			    break;
		}

		marker->setTransform(m);
		marker->setVisible(true);
		marker->setConfidence(markers[i].cf);
	    }
	}
	i++;
    }
}

TrackedObject* ARToolKitPlusTracker::getObject(const std::string name)
{
    for(std::vector<ARToolKitPlusTrackedObject *>::iterator it=this->objects.begin();
	it != this->objects.end();
	++it )
    {
	ARToolKitPlusTrackedObject *temp = *it;
	if(temp->getName()==name)
	    return temp;
    }

    return NULL;
}

std::vector<TrackedObject *> ARToolKitPlusTracker::getAllObjects()
{
    std::vector<TrackedObject *> v;
    for(std::vector<ARToolKitPlusTrackedObject *>::iterator it =
	this->objects.begin();
	it!=this->objects.end();
	++it)
	if( (*it)->isVisible())
	    v.push_back(*it);
    return v;
}

void ARToolKitPlusTracker::setUnits(Units u)
{
    this->scale = u;
}

void ARToolKitPlusTracker::setThreshold(const int value )
{
    if( value < 0 )
	this->tracker->activateAutoThreshold(true);
    else {
	this->tracker->activateAutoThreshold(false);
	this->tracker->setThreshold(value);
    }
}

void ARToolKitPlusTracker::toString()
{
    const char* description = this->tracker->getDescription();
    printf("ARToolKitPlus compile-time information:\n%s\n\n", description);
    printf("Thresholding: %s, current value %d\n",
	   this->tracker->isAutoThresholdActivated() ? "AUTO": "MANUAL",
	   this->tracker->getThreshold());
    printf("%d Markers found, %d is the id of best marker with a %f confidence\n",
	   this->markersFound,
	   this->bestMarker,
	   this->confidence);

    std::vector<TrackedObject *> allobjects = this->getAllObjects();
    for(std::vector<TrackedObject *>::iterator it = allobjects.begin();
	it != allobjects.end();
	++it ){
	ARToolKitPlusTrackedObject *marker = (ARToolKitPlusTrackedObject *)*it;
	printf("%5d : Confidence %f\n", marker->getID(), marker->getConfidence());
    }
    if( this->markersFound > 0 ){
	printf("Best Marker Matrix:\n");
	for(int i=0; i<16; i++)
	    printf("%.4f  %s", tracker->getModelViewMatrix()[i], (i%4==3)?"\n  " : "");
    }
}

/**
 * Get the projection matrix ARToolkit is using
 */
SMatrix ARToolKitPlusTracker::getProjectionMatrix()
{
    SMatrix m(4);
    const ARFloat *f = this->tracker->getProjectionMatrix();
    int i=0;
    for( int r=0; r<4;r++ ){
	for ( int c=0; c<4; c++)
	    m[c][r]=f[i++];

    }

    return m;
}

/**
 * Get the model view matrix of the best marker
 *
 * @return The model view matrix of the best marker
 */
SMatrix ARToolKitPlusTracker::getModelViewMatrix()
{
    SMatrix m(4);
    const ARFloat *f = this->tracker->getModelViewMatrix();
    int i=0;
    for( int r=0; r<4;r++ ){
	for ( int c=0; c<4; c++)
	    m[c][r]=f[i++];

    }

    return m;
};

Camera::CameraParameters ARToolKitPlusTracker::getParameters()
{
    if( this->camera->hasParameters())
	return this->camera->getParameters();

    printf("ARToolKitPlusTracker::getDistortion: There is no distortion matrix available for your camera\n"
	   "                      using a default, things may go strange near the edge of the image\n");

    Camera::CameraParameters d;

    d.intrinsicMatrix[0][0]=406.040405;
    d.intrinsicMatrix[0][1]=0.;
    d.intrinsicMatrix[0][2]=154.0;
    d.intrinsicMatrix[0][3]=0.;
    d.intrinsicMatrix[1][0]=0.;
    d.intrinsicMatrix[1][1]=404.388489;
    d.intrinsicMatrix[1][2]=115;
    d.intrinsicMatrix[1][3]=0;
    d.intrinsicMatrix[2][0]=0.;
    d.intrinsicMatrix[2][1]=0.;
    d.intrinsicMatrix[2][2]=1.;
    d.intrinsicMatrix[2][3]=0.;
    d.distortion[0]=159.;
    d.distortion[1]=139.;
    d.distortion[2]=-84.9000015;
    d.distortion[3]=0.979329705;

    return d;
}

}; // namespace wcl
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// mapnik
#include <mapnik/expression_node.hpp>
#include <mapnik/attribute.hpp>
#include <mapnik/value.hpp>

// boost
#include <boost/variant.hpp>

// icu
#include <unicode/uversion.h>

namespace mapnik
{

struct expression_string : boost::static_visitor<void>
{
    explicit expression_string(std::string & str)
        : str_(str) {}

    void operator() (value_type const& x) const
    {
        str_ += x.to_expression_string() ;
    }

    void operator() (attribute const& attr) const
    {
        str_ += "[";
        str_ += attr.name();
        str_ += "]";
    }

    void operator() (geometry_type_attribute const& attr) const
    {
        str_ += "[mapnik::geometry_type]";
    }

    template <typename Tag>
    void operator() (binary_node<Tag> const& x) const
    {
        if (x.type() != tags::mult::str() && x.type() != tags::div::str())
        {
            str_ += "(";
        }

        boost::apply_visitor(expression_string(str_),x.left);
        str_ += x.type();
        boost::apply_visitor(expression_string(str_),x.right);
        if (x.type() != tags::mult::str() && x.type() != tags::div::str())
        {
            str_ += ")";
        }
    }

    template <typename Tag>
    void operator() (unary_node<Tag> const& x) const
    {
        str_ += Tag::str();
        str_ += "(";
        boost::apply_visitor(expression_string(str_),x.expr);
        str_ += ")";
    }

    void operator() (regex_match_node const & x) const
    {
        boost::apply_visitor(expression_string(str_),x.expr);
        str_ +=".match('";
#if defined(BOOST_REGEX_HAS_ICU)
        std::string utf8;
        UnicodeString ustr = UnicodeString::fromUTF32( &x.pattern.str()[0] ,x.pattern.str().length());
        to_utf8(ustr,utf8);
        str_ += utf8;
#else
        str_ += x.pattern.str();
#endif
        str_ +="')";
    }

    void operator() (regex_replace_node const & x) const
    {
        boost::apply_visitor(expression_string(str_),x.expr);
        str_ +=".replace(";
        str_ += "'";
#if defined(BOOST_REGEX_HAS_ICU)
        std::string utf8;
        UnicodeString ustr = UnicodeString::fromUTF32( &x.pattern.str()[0] ,x.pattern.str().length());
        to_utf8(ustr,utf8);
        str_ += utf8;
        str_ +="','";
        to_utf8(x.format ,utf8);
        str_ += utf8;
#else
        str_ += x.pattern.str();
        str_ +="','";
        str_ += x.format;
#endif
        str_ +="')";
    }

private:
    std::string & str_;
};

std::string to_expression_string(expr_node const& node)
{
    std::string str;
    expression_string functor(str);
    boost::apply_visitor(functor,node);
    return str;
}

}
<commit_msg>fixup includes in expression_string.cpp<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// mapnik

#include <mapnik/config.hpp> // needed by msvc
#include <mapnik/expression_string.hpp> // needed by msvc
#include <mapnik/expression_node_types.hpp>
#include <mapnik/expression_node.hpp>
#include <mapnik/attribute.hpp>
#include <mapnik/value.hpp>

// boost
#include <boost/variant.hpp>
#if defined(BOOST_REGEX_HAS_ICU)
#include <boost/regex/icu.hpp>          // for u32regex
#endif

// icu
#include <unicode/unistr.h>             // for UnicodeString

namespace mapnik
{

struct expression_string : boost::static_visitor<void>
{
    explicit expression_string(std::string & str)
        : str_(str) {}

    void operator() (value_type const& x) const
    {
        str_ += x.to_expression_string() ;
    }

    void operator() (attribute const& attr) const
    {
        str_ += "[";
        str_ += attr.name();
        str_ += "]";
    }

    void operator() (geometry_type_attribute const& attr) const
    {
        str_ += "[mapnik::geometry_type]";
    }

    template <typename Tag>
    void operator() (binary_node<Tag> const& x) const
    {
        if (x.type() != tags::mult::str() && x.type() != tags::div::str())
        {
            str_ += "(";
        }

        boost::apply_visitor(expression_string(str_),x.left);
        str_ += x.type();
        boost::apply_visitor(expression_string(str_),x.right);
        if (x.type() != tags::mult::str() && x.type() != tags::div::str())
        {
            str_ += ")";
        }
    }

    template <typename Tag>
    void operator() (unary_node<Tag> const& x) const
    {
        str_ += Tag::str();
        str_ += "(";
        boost::apply_visitor(expression_string(str_),x.expr);
        str_ += ")";
    }

    void operator() (regex_match_node const & x) const
    {
        boost::apply_visitor(expression_string(str_),x.expr);
        str_ +=".match('";
#if defined(BOOST_REGEX_HAS_ICU)
        std::string utf8;
        UnicodeString ustr = UnicodeString::fromUTF32( &x.pattern.str()[0] ,x.pattern.str().length());
        to_utf8(ustr,utf8);
        str_ += utf8;
#else
        str_ += x.pattern.str();
#endif
        str_ +="')";
    }

    void operator() (regex_replace_node const & x) const
    {
        boost::apply_visitor(expression_string(str_),x.expr);
        str_ +=".replace(";
        str_ += "'";
#if defined(BOOST_REGEX_HAS_ICU)
        std::string utf8;
        UnicodeString ustr = UnicodeString::fromUTF32( &x.pattern.str()[0] ,x.pattern.str().length());
        to_utf8(ustr,utf8);
        str_ += utf8;
        str_ +="','";
        to_utf8(x.format ,utf8);
        str_ += utf8;
#else
        str_ += x.pattern.str();
        str_ +="','";
        str_ += x.format;
#endif
        str_ +="')";
    }

private:
    std::string & str_;
};

std::string to_expression_string(expr_node const& node)
{
    std::string str;
    expression_string functor(str);
    boost::apply_visitor(functor,node);
    return str;
}

}
<|endoftext|>


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

#include "testing/gtest/include/gtest/gtest.h"

#include "base/file_util.h"
#include "base/path_service.h"
#include "base/time.h"
#include "chrome/browser/bookmarks/bookmark_html_writer.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/importer/firefox2_importer.h"

class BookmarkHTMLWriterTest : public testing::Test {
 protected:
  virtual void SetUp() {
    ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &path_));
    path_ = path_.AppendASCII("bookmarks.html");
    file_util::Delete(path_, true);
  }

  virtual void TearDown() {
    if (!path_.empty())
      file_util::Delete(path_, true);
  }

  void AssertBookmarkEntryEquals(const ProfileWriter::BookmarkEntry& entry,
                                 bool on_toolbar,
                                 const GURL& url,
                                 const std::wstring& title,
                                 base::Time creation_time,
                                 const std::wstring& f1,
                                 const std::wstring& f2,
                                 const std::wstring& f3) {
    EXPECT_EQ(on_toolbar, entry.in_toolbar);
    EXPECT_TRUE(url == entry.url);
    EXPECT_EQ(title, entry.title);
    EXPECT_TRUE(creation_time.ToTimeT() == entry.creation_time.ToTimeT());
    size_t path_count = 0;
    if (!f3.empty())
      path_count = 3;
    else if (!f2.empty())
      path_count = 2;
    else if (!f1.empty())
      path_count = 1;
    // The first path element should always be 'x', as that is what we passed
    // to the importer.
    ASSERT_EQ(path_count + 1, entry.path.size());
    EXPECT_EQ(L"x", entry.path[0]);
    EXPECT_TRUE(path_count < 1 || entry.path[1] == f1);
    EXPECT_TRUE(path_count < 2 || entry.path[2] == f2);
    EXPECT_TRUE(path_count < 3 || entry.path[3] == f3);
  }

  FilePath path_;
};

// Tests bookmark_html_writer by populating a BookmarkModel, writing it out by
// way of bookmark_html_writer, then using the importer to read it back in.
TEST_F(BookmarkHTMLWriterTest, DISABLED_Test) {
  // Populate the BookmarkModel. This creates the following bookmark structure:
  // Bookmarks bar
  //   F1
  //     url1
  //     F2
  //       url2
  //   url3
  //   url4
  // Other
  //   url1
  //   url2
  //   F3
  //     F4
  //       url1
  std::wstring f1_title = L"F\"&;<1\"";
  std::wstring f2_title = L"F2";
  std::wstring f3_title = L"F 3";
  std::wstring f4_title = L"F4";
  std::wstring url1_title = L"url 1";
  std::wstring url2_title = L"url&2";
  std::wstring url3_title = L"url\"3";
  std::wstring url4_title = L"url\"&;";
  GURL url1("http://url1");
  GURL url2("http://url2");
  GURL url3("http://url3");
  GURL url4("http://\"&;\"");
  BookmarkModel model(NULL);
  base::Time t1(base::Time::Now());
  base::Time t2(t1 + base::TimeDelta::FromHours(1));
  base::Time t3(t1 + base::TimeDelta::FromHours(1));
  base::Time t4(t1 + base::TimeDelta::FromHours(1));
  const BookmarkNode* f1 = model.AddGroup(
      model.GetBookmarkBarNode(), 0, f1_title);
  model.AddURLWithCreationTime(f1, 0, url1_title, url1, t1);
  const BookmarkNode* f2 = model.AddGroup(f1, 1, f2_title);
  model.AddURLWithCreationTime(f2, 0, url2_title, url2, t2);
  model.AddURLWithCreationTime(model.GetBookmarkBarNode(), 1, url3_title, url3,
                               t3);

  model.AddURLWithCreationTime(model.other_node(), 0, url1_title, url1, t1);
  model.AddURLWithCreationTime(model.other_node(), 1, url2_title, url2, t2);
  const BookmarkNode* f3 = model.AddGroup(model.other_node(), 2, f3_title);
  const BookmarkNode* f4 = model.AddGroup(f3, 0, f4_title);
  model.AddURLWithCreationTime(f4, 0, url1_title, url1, t1);
  model.AddURLWithCreationTime(model.GetBookmarkBarNode(), 2, url4_title,
                              url4, t4);

  // Write to a temp file.
  bookmark_html_writer::WriteBookmarks(NULL, &model, path_);

  // Read the bookmarks back in.
  std::vector<ProfileWriter::BookmarkEntry> parsed_bookmarks;
  Firefox2Importer::ImportBookmarksFile(path_.ToWStringHack(), std::set<GURL>(),
                                        false, L"x", NULL, &parsed_bookmarks,
                                        NULL, NULL);

  // Verify we got back what we wrote.
  ASSERT_EQ(7U, parsed_bookmarks.size());
  // Hardcode the value of IDS_BOOKMARK_BAR_FOLDER_NAME in en-US locale
  // because all the unit tests are run in en-US locale.
  const wchar_t* kBookmarkBarFolderName = L"Bookmarks bar";
  AssertBookmarkEntryEquals(parsed_bookmarks[0], false, url1, url1_title, t1,
                            kBookmarkBarFolderName, f1_title, std::wstring());
  AssertBookmarkEntryEquals(parsed_bookmarks[1], false, url2, url2_title, t2,
                            kBookmarkBarFolderName, f1_title, f2_title);
  AssertBookmarkEntryEquals(parsed_bookmarks[2], false, url3, url3_title, t3,
                            kBookmarkBarFolderName, std::wstring(),
                            std::wstring());
  AssertBookmarkEntryEquals(parsed_bookmarks[3], false, url4, url4_title, t4,
                            kBookmarkBarFolderName, std::wstring(),
                            std::wstring());
  AssertBookmarkEntryEquals(parsed_bookmarks[4], false, url1, url1_title, t1,
                            std::wstring(), std::wstring(), std::wstring());
  AssertBookmarkEntryEquals(parsed_bookmarks[5], false, url2, url2_title, t2,
                            std::wstring(), std::wstring(), std::wstring());
  AssertBookmarkEntryEquals(parsed_bookmarks[6], false, url1, url1_title, t1,
                            f3_title, f4_title, std::wstring());
}
<commit_msg>Reenables BookmarkHTMLWriterTest.  I couldn't repro a failure on my machine after running the test all night, so I'm reenabling the test and making the output more humany readable so that if it does fail hopefully we can figure out where it's going wrong.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "testing/gtest/include/gtest/gtest.h"

#include "base/file_util.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/time.h"
#include "base/time_format.h"
#include "chrome/browser/bookmarks/bookmark_html_writer.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/importer/firefox2_importer.h"

class BookmarkHTMLWriterTest : public testing::Test {
 protected:
  virtual void SetUp() {
    ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &path_));
    path_ = path_.AppendASCII("bookmarks.html");
    file_util::Delete(path_, true);
  }

  virtual void TearDown() {
    if (!path_.empty())
      file_util::Delete(path_, true);
  }

  // Converts a BookmarkEntry to a string suitable for assertion testing.
  std::wstring BookmarkEntryToString(
      const ProfileWriter::BookmarkEntry& entry) {
    std::wstring result;
    result.append(L"on_toolbar=");
    if (entry.in_toolbar)
      result.append(L"false");
    else
      result.append(L"true");

    result.append(L" url=" + UTF8ToWide(entry.url.spec()));

    result.append(L" path=");
    for (size_t i = 0; i < entry.path.size(); ++i) {
      if (i != 0)
        result.append(L"/");
      result.append(entry.path[i]);
    }

    result.append(L" title=");
    result.append(entry.title);

    result.append(L" time=");
    result.append(base::TimeFormatFriendlyDateAndTime(entry.creation_time));
    return result;
  }

  // Creates a set of bookmark values to a string for assertion testing.
  std::wstring BookmarkValuesToString(bool on_toolbar,
                                      const GURL& url,
                                      const std::wstring& title,
                                      base::Time creation_time,
                                      const std::wstring& f1,
                                      const std::wstring& f2,
                                      const std::wstring& f3) {
    ProfileWriter::BookmarkEntry entry;
    entry.in_toolbar = on_toolbar;
    entry.url = url;
    // The first path element should always be 'x', as that is what we passed
    // to the importer.
    entry.path.push_back(L"x");
    if (!f1.empty()) {
      entry.path.push_back(f1);
      if (!f2.empty()) {
        entry.path.push_back(f2);
        if (!f3.empty())
          entry.path.push_back(f3);
      }
    }
    entry.title = title;
    entry.creation_time = creation_time;
    return BookmarkEntryToString(entry);
  }

  void AssertBookmarkEntryEquals(const ProfileWriter::BookmarkEntry& entry,
                                 bool on_toolbar,
                                 const GURL& url,
                                 const std::wstring& title,
                                 base::Time creation_time,
                                 const std::wstring& f1,
                                 const std::wstring& f2,
                                 const std::wstring& f3) {
    EXPECT_EQ(BookmarkValuesToString(on_toolbar, url, title, creation_time,
                                     f1, f2, f3),
              BookmarkEntryToString(entry));
  }

  FilePath path_;
};

// Tests bookmark_html_writer by populating a BookmarkModel, writing it out by
// way of bookmark_html_writer, then using the importer to read it back in.
TEST_F(BookmarkHTMLWriterTest, Test) {
  // Populate the BookmarkModel. This creates the following bookmark structure:
  // Bookmarks bar
  //   F1
  //     url1
  //     F2
  //       url2
  //   url3
  //   url4
  // Other
  //   url1
  //   url2
  //   F3
  //     F4
  //       url1
  std::wstring f1_title = L"F\"&;<1\"";
  std::wstring f2_title = L"F2";
  std::wstring f3_title = L"F 3";
  std::wstring f4_title = L"F4";
  std::wstring url1_title = L"url 1";
  std::wstring url2_title = L"url&2";
  std::wstring url3_title = L"url\"3";
  std::wstring url4_title = L"url\"&;";
  GURL url1("http://url1");
  GURL url2("http://url2");
  GURL url3("http://url3");
  GURL url4("http://\"&;\"");
  BookmarkModel model(NULL);
  base::Time t1(base::Time::Now());
  base::Time t2(t1 + base::TimeDelta::FromHours(1));
  base::Time t3(t1 + base::TimeDelta::FromHours(1));
  base::Time t4(t1 + base::TimeDelta::FromHours(1));
  const BookmarkNode* f1 = model.AddGroup(
      model.GetBookmarkBarNode(), 0, f1_title);
  model.AddURLWithCreationTime(f1, 0, url1_title, url1, t1);
  const BookmarkNode* f2 = model.AddGroup(f1, 1, f2_title);
  model.AddURLWithCreationTime(f2, 0, url2_title, url2, t2);
  model.AddURLWithCreationTime(model.GetBookmarkBarNode(), 1, url3_title, url3,
                               t3);

  model.AddURLWithCreationTime(model.other_node(), 0, url1_title, url1, t1);
  model.AddURLWithCreationTime(model.other_node(), 1, url2_title, url2, t2);
  const BookmarkNode* f3 = model.AddGroup(model.other_node(), 2, f3_title);
  const BookmarkNode* f4 = model.AddGroup(f3, 0, f4_title);
  model.AddURLWithCreationTime(f4, 0, url1_title, url1, t1);
  model.AddURLWithCreationTime(model.GetBookmarkBarNode(), 2, url4_title,
                              url4, t4);

  // Write to a temp file.
  bookmark_html_writer::WriteBookmarks(NULL, &model, path_);

  // Read the bookmarks back in.
  std::vector<ProfileWriter::BookmarkEntry> parsed_bookmarks;
  Firefox2Importer::ImportBookmarksFile(path_.ToWStringHack(), std::set<GURL>(),
                                        false, L"x", NULL, &parsed_bookmarks,
                                        NULL, NULL);

  // Verify we got back what we wrote.
  ASSERT_EQ(7U, parsed_bookmarks.size());
  // Hardcode the value of IDS_BOOKMARK_BAR_FOLDER_NAME in en-US locale
  // because all the unit tests are run in en-US locale.
  const wchar_t* kBookmarkBarFolderName = L"Bookmarks bar";
  AssertBookmarkEntryEquals(parsed_bookmarks[0], false, url1, url1_title, t1,
                            kBookmarkBarFolderName, f1_title, std::wstring());
  AssertBookmarkEntryEquals(parsed_bookmarks[1], false, url2, url2_title, t2,
                            kBookmarkBarFolderName, f1_title, f2_title);
  AssertBookmarkEntryEquals(parsed_bookmarks[2], false, url3, url3_title, t3,
                            kBookmarkBarFolderName, std::wstring(),
                            std::wstring());
  AssertBookmarkEntryEquals(parsed_bookmarks[3], false, url4, url4_title, t4,
                            kBookmarkBarFolderName, std::wstring(),
                            std::wstring());
  AssertBookmarkEntryEquals(parsed_bookmarks[4], false, url1, url1_title, t1,
                            std::wstring(), std::wstring(), std::wstring());
  AssertBookmarkEntryEquals(parsed_bookmarks[5], false, url2, url2_title, t2,
                            std::wstring(), std::wstring(), std::wstring());
  AssertBookmarkEntryEquals(parsed_bookmarks[6], false, url1, url1_title, t1,
                            f3_title, f4_title, std::wstring());
}
<|endoftext|>


<commit_before>#include <export.hpp>

#include <kdb.hpp>
#include <modules.hpp>
#include <cmdline.hpp>
#include <toolexcept.hpp>

#include <iostream>

using namespace std;
using namespace kdb;
using namespace kdb::tools;

ExportCommand::ExportCommand()
{}

int ExportCommand::execute(Cmdline const& cl)
{
	size_t argc = cl.arguments.size();
	if (argc != 1 && argc != 2 && argc != 3)
	{
		throw invalid_argument("need 1 to 3 arguments");
	}

	Key root (cl.arguments[0], KEY_END);
	if (!root.isValid())
	{
		throw invalid_argument ("root key is not a valid key name");
	}

	kdb.get(ks, root);
	printWarnings(cerr, root);

	KeySet part (ks.cut(root));

	string format = "dump";
	if (argc > 1) format = cl.arguments[1];

	string file = "/dev/stdout";
	if (argc > 2 && cl.arguments[2] != "-") file = cl.arguments[2];

	Modules modules;
	PluginPtr plugin = modules.load(format);

	Key errorKey;
	errorKey.setString(file);

	plugin->set(part, errorKey);

	printWarnings(cerr, errorKey);
	printError(cerr, errorKey);

	return 0;
}

ExportCommand::~ExportCommand()
{}
<commit_msg>fix export accordingly<commit_after>#include <export.hpp>

#include <kdb.hpp>
#include <modules.hpp>
#include <cmdline.hpp>
#include <toolexcept.hpp>

#include <iostream>

using namespace std;
using namespace kdb;
using namespace kdb::tools;

ExportCommand::ExportCommand()
{}

int ExportCommand::execute(Cmdline const& cl)
{
	size_t argc = cl.arguments.size();
	if (argc != 1 && argc != 2 && argc != 3)
	{
		throw invalid_argument("need 1 to 3 arguments");
	}

	Key root (cl.arguments[0], KEY_END);
	if (!root.isValid())
	{
		throw invalid_argument ("root key is not a valid key name");
	}

	kdb.get(ks, root);
	printWarnings(cerr, root);

	KeySet part (ks.cut(root));

	string format = "dump";
	if (argc > 1) format = cl.arguments[1];

	string file = "/dev/stdout";
	if (argc > 2 && cl.arguments[2] != "-") file = cl.arguments[2];

	Modules modules;
	PluginPtr plugin = modules.load(format);

	Key errorKey(root);
	errorKey.setString(file);

	plugin->set(part, errorKey);

	printWarnings(cerr, errorKey);
	printError(cerr, errorKey);

	return 0;
}

ExportCommand::~ExportCommand()
{}
<|endoftext|>


<commit_before>// -*- C++ -*-
// ex0_scalarIntegrator.cc
// an exercise for the sandia 2014 clinic team.
// here we integrate sin over some interval using various methods

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <array>
#include <string>
#include <chrono>

// header file for openmp
#include <omp.h>

// header files for tbb
#include <tbb/blocked_range.h>
#include <tbb/parallel_reduce.h>
#include <tbb/parallel_for.h>
#include <tbb/task_scheduler_init.h>

// header files for cuda implementation
#include "ex0_scalarIntegrator_cuda.cuh"

// header files for kokkos
#include <Kokkos_Core.hpp>

using std::string;
using std::vector;
using std::array;
using std::chrono::high_resolution_clock;
using std::chrono::duration;
using std::chrono::duration_cast;

class myFunctor {
public:
  myFunctor() {

  }

  double operator()(double functionInput) {
    return std::sin(functionInput);
  }
};

class TbbOutputter {
public:

  const double startingPoint_;

  const double dx_;

  myFunctor function_;

  double sum_;

  TbbOutputter(const double startingPoint, const double dx, myFunctor
    function) :
    startingPoint_(startingPoint), dx_(dx), function_(function), sum_(0) {
  }

  TbbOutputter(const TbbOutputter & other,
               tbb::split) :
    startingPoint_(other.startingPoint_), dx_(other.dx_),
    function_(other.function_), sum_(0) {

  }

  void operator()(const tbb::blocked_range<size_t> & range) {

    double sum = sum_;

    for(unsigned int i=range.begin(); i!= range.end(); ++i )
            sum += function_(startingPoint_ + (double(i) + .5) * dx_);

    sum_ = sum;
  }

  void join(const TbbOutputter & other) {
    sum_ += other.sum_;
  }

private:
  TbbOutputter();

};

struct KokkosFunctor {

  const double _dx;

  KokkosFunctor(const double dx) : _dx(dx) {
  }

  KOKKOS_INLINE_FUNCTION
  void operator()(const unsigned int intervalIndex) const {
  }

private:
  KokkosFunctor();

};

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

  // a couple of inputs.  change the numberOfIntervals to control the amount
  //  of work done
  const unsigned long numberOfIntervals = 1e2;
  // the integration bounds
  const array<double, 2> bounds = {{0, 1.314}};

  // these are c++ timers...for timing
  high_resolution_clock::time_point tic;
  high_resolution_clock::time_point toc;

  const double dx = (bounds[1] - bounds[0]) / numberOfIntervals;

  // calculate analytic solution
  const double libraryAnswer =
    std::cos(bounds[0]) - std::cos(bounds[1]);

  // ===============================================================
  // ********************** < do slow serial> **********************
  // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

  double slowSerialIntegral = 0;
  tic = high_resolution_clock::now();
  for (unsigned int intervalIndex = 0;
       intervalIndex < numberOfIntervals; ++intervalIndex) {
    if (intervalIndex % (numberOfIntervals / 10) == 0) {
      printf("serial calculation on interval %8.2e / %8.2e (%%%5.1f)\n",
             double(intervalIndex),
             double(numberOfIntervals),
             100. * intervalIndex / double(numberOfIntervals));
    }
    const double evaluationPoint =
      bounds[0] + (double(intervalIndex) + 0.5) * dx;
    slowSerialIntegral += std::sin(evaluationPoint);
  }
  slowSerialIntegral *= dx;
  toc = high_resolution_clock::now();
  const double slowSerialElapsedTime =
    duration_cast<duration<double> >(toc - tic).count();

  // check our serial answer
  const double serialRelativeError =
    std::abs(libraryAnswer - slowSerialIntegral) / std::abs(libraryAnswer);
  if (serialRelativeError > 1e-3) {
    fprintf(stderr, "our answer is too far off: %15.8e instead of %15.8e\n",
            slowSerialIntegral, libraryAnswer);
    exit(1);
  }

  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // ********************** </do slow serial> **********************
  // ===============================================================

  // ===============================================================
  // ********************** < do fast serial> **********************
  // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

  const double fastSerialIntegral = slowSerialIntegral;
  const double fastSerialElapsedTime = slowSerialElapsedTime;

  // check our serial answer
  const double fastSerialRelativeError =
    std::abs(libraryAnswer - fastSerialIntegral) / std::abs(libraryAnswer);
  if (fastSerialRelativeError > 1e-3) {
    fprintf(stderr, "our answer is too far off: %15.8e instead of %15.8e\n",
            fastSerialIntegral, libraryAnswer);
    exit(1);
  }

  // output speedup
  printf("fast: time %8.2e speedup %8.2e\n",
         fastSerialElapsedTime,
         slowSerialElapsedTime / fastSerialElapsedTime);

  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // ********************** </do fast serial> **********************
  // ===============================================================

  // we will repeat the computation for each of the numbers of threads
  vector<unsigned int> numberOfThreadsArray;
  numberOfThreadsArray.push_back(1);
  numberOfThreadsArray.push_back(2);
  numberOfThreadsArray.push_back(4);
  numberOfThreadsArray.push_back(8);
  numberOfThreadsArray.push_back(16);
  numberOfThreadsArray.push_back(24);

  // ===============================================================
  // ********************** < do tbb> ******************************
  // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

  printf("performing calculations with tbb\n");
  // for each number of threads
  for (const unsigned int numberOfThreads :
         numberOfThreadsArray) {

    // initialize tbb's threading system for this number of threads
    tbb::task_scheduler_init init(numberOfThreads);

    TbbOutputter tbbOutputter(bounds[0], dx, myFunctor);

    // start timing
    tic = high_resolution_clock::now();
    // dispatch threads
    parallel_reduce(tbb::blocked_range<size_t>(0, numberOfIntervals),
                    tbbOutputter);
    // stop timing
    toc = high_resolution_clock::now();
    const double threadedElapsedTime =
      duration_cast<duration<double> >(toc - tic).count();

    // somehow get the threaded integral answer
    const double threadedIntegral = tbbOutputter.sum_ * dx;
    // check the answer
    const double threadedRelativeError =
      std::abs(libraryAnswer - threadedIntegral) / std::abs(libraryAnswer);

    if (threadedRelativeError > 1e-3) {
      fprintf(stderr, "our answer is too far off: %15.8e instead of %15.8e\n",
              threadedIntegral, libraryAnswer);
      exit(1);
    }

    // output speedup
    printf("%3u : time %8.2e speedup %8.2e (%%%5.1f of ideal)\n",
           numberOfThreads,
           threadedElapsedTime,
           fastSerialElapsedTime / threadedElapsedTime,
           100. * fastSerialElapsedTime / threadedElapsedTime / numberOfThreads);
  }

  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // ********************** </do tbb> ******************************
  // ===============================================================

  // ===============================================================
  // ********************** < do openmp> ***************************
  // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

  printf("performing calculations with openmp\n");
  // for each number of threads
  for (const unsigned int numberOfThreads :
         numberOfThreadsArray) {

    double threadedIntegral = 0;
    // start timing
    tic = high_resolution_clock::now();

    #pragma omp parallel num_threads(numberOfThreads)
    {

    }

    // stop timing
    toc = high_resolution_clock::now();
    const double threadedElapsedTime =
      duration_cast<duration<double> >(toc - tic).count();

    // check the answer
    const double threadedRelativeError =
      std::abs(libraryAnswer - threadedIntegral) / std::abs(libraryAnswer);
    if (threadedRelativeError !=0) {
      fprintf(stderr, "our answer is too far off: %15.8e instead of %15.8e\n",
              threadedIntegral, libraryAnswer);
      exit(1);
    }

    // output speedup
    printf("%3u : time %8.2e speedup %8.2e (%%%5.1f of ideal)\n",
           numberOfThreads,
           threadedElapsedTime,
           fastSerialElapsedTime / threadedElapsedTime,
           100. * fastSerialElapsedTime / threadedElapsedTime / numberOfThreads);
  }

  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // ********************** </do openmp> ***************************
  // ===============================================================

  // ===============================================================
  // ********************** < do cuda> *****************************
  // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

  // we will repeat the computation for each of the numbers of threads
  vector<unsigned int> threadsPerBlockArray;
  threadsPerBlockArray.push_back(32);
  threadsPerBlockArray.push_back(64);
  threadsPerBlockArray.push_back(128);
  threadsPerBlockArray.push_back(256);
  threadsPerBlockArray.push_back(512);

  printf("performing calculations with cuda\n");
  // for each number of threads per block
  for (const unsigned int numberOfThreadsPerBlock :
         threadsPerBlockArray) {

    double cudaIntegral = 0;
    // start timing
    tic = high_resolution_clock::now();

    // stop timing
    toc = high_resolution_clock::now();
    const double cudaElapsedTime =
      duration_cast<duration<double> >(toc - tic).count();

    // check the answer
    const double cudaRelativeError =
      std::abs(libraryAnswer - cudaIntegral) / std::abs(libraryAnswer);
    if (cudaRelativeError > 1e-3) {
      fprintf(stderr, "our answer is too far off: %15.8e instead of %15.8e\n",
              cudaIntegral, libraryAnswer);
      exit(1);
    }

    // output speedup
    printf("%3u : time %8.2e speedup %8.2e\n",
           numberOfThreadsPerBlock,
           cudaElapsedTime,
           fastSerialElapsedTime / cudaElapsedTime);
  }

  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // ********************** </do cuda> *****************************
  // ===============================================================

  // ===============================================================
  // ********************** < do kokkos> *****************************
  // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

  printf("performing calculations with kokkos on %s\n",
         typeid(Kokkos::DefaultExecutionSpace).name());

  Kokkos::initialize();

  const KokkosFunctor kokkosFunctor(dx);

  // start timing
  tic = high_resolution_clock::now();

  const double kokkosIntegral = 0;
  // TODO: calculate integral using kokkos

  // stop timing
  toc = high_resolution_clock::now();
  const double kokkosElapsedTime =
    duration_cast<duration<double> >(toc - tic).count();

  // check the answer
  const double kokkosRelativeError =
    std::abs(libraryAnswer - kokkosIntegral) / std::abs(libraryAnswer);
  if (kokkosRelativeError > 1e-3) {
    fprintf(stderr, "our answer is too far off: %15.8e instead of %15.8e\n",
            kokkosIntegral, libraryAnswer);
    exit(1);
  }

  // output speedup
  printf("kokkos : time %8.2e speedup %8.2e\n",
         kokkosElapsedTime,
         fastSerialElapsedTime / kokkosElapsedTime);

  Kokkos::finalize();

  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // ********************** </do kokkos> ***************************
  // ===============================================================

  return 0;
}
<commit_msg>syntax<commit_after>// -*- C++ -*-
// ex0_scalarIntegrator.cc
// an exercise for the sandia 2014 clinic team.
// here we integrate sin over some interval using various methods

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <array>
#include <string>
#include <chrono>

// header file for openmp
#include <omp.h>

// header files for tbb
#include <tbb/blocked_range.h>
#include <tbb/parallel_reduce.h>
#include <tbb/parallel_for.h>
#include <tbb/task_scheduler_init.h>

// header files for cuda implementation
#include "ex0_scalarIntegrator_cuda.cuh"

// header files for kokkos
#include <Kokkos_Core.hpp>

using std::string;
using std::vector;
using std::array;
using std::chrono::high_resolution_clock;
using std::chrono::duration;
using std::chrono::duration_cast;

class myFunctor {
public:
  myFunctor() {

  }

  double operator()(double functionInput) {
    return std::sin(functionInput);
  }
};

class TbbOutputter {
public:

  const double startingPoint_;

  const double dx_;

  myFunctor function_;

  double sum_;

  TbbOutputter(const double startingPoint, const double dx, myFunctor
    function) :
    startingPoint_(startingPoint), dx_(dx), function_(function), sum_(0) {
  }

  TbbOutputter(const TbbOutputter & other,
               tbb::split) :
    startingPoint_(other.startingPoint_), dx_(other.dx_),
    function_(other.function_), sum_(0) {

  }

  void operator()(const tbb::blocked_range<size_t> & range) {

    double sum = sum_;

    for(unsigned int i=range.begin(); i!= range.end(); ++i )
            sum += function_(startingPoint_ + (double(i) + .5) * dx_);

    sum_ = sum;
  }

  void join(const TbbOutputter & other) {
    sum_ += other.sum_;
  }

private:
  TbbOutputter();

};

struct KokkosFunctor {

  const double _dx;

  KokkosFunctor(const double dx) : _dx(dx) {
  }

  KOKKOS_INLINE_FUNCTION
  void operator()(const unsigned int intervalIndex) const {
  }

private:
  KokkosFunctor();

};

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

  // a couple of inputs.  change the numberOfIntervals to control the amount
  //  of work done
  const unsigned long numberOfIntervals = 1e2;
  // the integration bounds
  const array<double, 2> bounds = {{0, 1.314}};

  // these are c++ timers...for timing
  high_resolution_clock::time_point tic;
  high_resolution_clock::time_point toc;

  const double dx = (bounds[1] - bounds[0]) / numberOfIntervals;

  // calculate analytic solution
  const double libraryAnswer =
    std::cos(bounds[0]) - std::cos(bounds[1]);

  // ===============================================================
  // ********************** < do slow serial> **********************
  // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

  double slowSerialIntegral = 0;
  tic = high_resolution_clock::now();
  for (unsigned int intervalIndex = 0;
       intervalIndex < numberOfIntervals; ++intervalIndex) {
    if (intervalIndex % (numberOfIntervals / 10) == 0) {
      printf("serial calculation on interval %8.2e / %8.2e (%%%5.1f)\n",
             double(intervalIndex),
             double(numberOfIntervals),
             100. * intervalIndex / double(numberOfIntervals));
    }
    const double evaluationPoint =
      bounds[0] + (double(intervalIndex) + 0.5) * dx;
    slowSerialIntegral += std::sin(evaluationPoint);
  }
  slowSerialIntegral *= dx;
  toc = high_resolution_clock::now();
  const double slowSerialElapsedTime =
    duration_cast<duration<double> >(toc - tic).count();

  // check our serial answer
  const double serialRelativeError =
    std::abs(libraryAnswer - slowSerialIntegral) / std::abs(libraryAnswer);
  if (serialRelativeError > 1e-3) {
    fprintf(stderr, "our answer is too far off: %15.8e instead of %15.8e\n",
            slowSerialIntegral, libraryAnswer);
    exit(1);
  }

  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // ********************** </do slow serial> **********************
  // ===============================================================

  // ===============================================================
  // ********************** < do fast serial> **********************
  // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

  const double fastSerialIntegral = slowSerialIntegral;
  const double fastSerialElapsedTime = slowSerialElapsedTime;

  // check our serial answer
  const double fastSerialRelativeError =
    std::abs(libraryAnswer - fastSerialIntegral) / std::abs(libraryAnswer);
  if (fastSerialRelativeError > 1e-3) {
    fprintf(stderr, "our answer is too far off: %15.8e instead of %15.8e\n",
            fastSerialIntegral, libraryAnswer);
    exit(1);
  }

  // output speedup
  printf("fast: time %8.2e speedup %8.2e\n",
         fastSerialElapsedTime,
         slowSerialElapsedTime / fastSerialElapsedTime);

  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // ********************** </do fast serial> **********************
  // ===============================================================

  // we will repeat the computation for each of the numbers of threads
  vector<unsigned int> numberOfThreadsArray;
  numberOfThreadsArray.push_back(1);
  numberOfThreadsArray.push_back(2);
  numberOfThreadsArray.push_back(4);
  numberOfThreadsArray.push_back(8);
  numberOfThreadsArray.push_back(16);
  numberOfThreadsArray.push_back(24);

  // ===============================================================
  // ********************** < do tbb> ******************************
  // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  myFunctor function;
  printf("performing calculations with tbb\n");
  // for each number of threads
  for (const unsigned int numberOfThreads :
         numberOfThreadsArray) {

    // initialize tbb's threading system for this number of threads
    tbb::task_scheduler_init init(numberOfThreads);

    TbbOutputter tbbOutputter(bounds[0], dx, function);

    // start timing
    tic = high_resolution_clock::now();
    // dispatch threads
    parallel_reduce(tbb::blocked_range<size_t>(0, numberOfIntervals),
                    tbbOutputter);
    // stop timing
    toc = high_resolution_clock::now();
    const double threadedElapsedTime =
      duration_cast<duration<double> >(toc - tic).count();

    // somehow get the threaded integral answer
    const double threadedIntegral = tbbOutputter.sum_ * dx;
    // check the answer
    const double threadedRelativeError =
      std::abs(libraryAnswer - threadedIntegral) / std::abs(libraryAnswer);

    if (threadedRelativeError > 1e-3) {
      fprintf(stderr, "our answer is too far off: %15.8e instead of %15.8e\n",
              threadedIntegral, libraryAnswer);
      exit(1);
    }

    // output speedup
    printf("%3u : time %8.2e speedup %8.2e (%%%5.1f of ideal)\n",
           numberOfThreads,
           threadedElapsedTime,
           fastSerialElapsedTime / threadedElapsedTime,
           100. * fastSerialElapsedTime / threadedElapsedTime / numberOfThreads);
  }

  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // ********************** </do tbb> ******************************
  // ===============================================================

  // ===============================================================
  // ********************** < do openmp> ***************************
  // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

  printf("performing calculations with openmp\n");
  // for each number of threads
  for (const unsigned int numberOfThreads :
         numberOfThreadsArray) {

    double threadedIntegral = 0;
    // start timing
    tic = high_resolution_clock::now();

    #pragma omp parallel num_threads(numberOfThreads)
    {

    }

    // stop timing
    toc = high_resolution_clock::now();
    const double threadedElapsedTime =
      duration_cast<duration<double> >(toc - tic).count();

    // check the answer
    const double threadedRelativeError =
      std::abs(libraryAnswer - threadedIntegral) / std::abs(libraryAnswer);
    if (threadedRelativeError !=0) {
      fprintf(stderr, "our answer is too far off: %15.8e instead of %15.8e\n",
              threadedIntegral, libraryAnswer);
      exit(1);
    }

    // output speedup
    printf("%3u : time %8.2e speedup %8.2e (%%%5.1f of ideal)\n",
           numberOfThreads,
           threadedElapsedTime,
           fastSerialElapsedTime / threadedElapsedTime,
           100. * fastSerialElapsedTime / threadedElapsedTime / numberOfThreads);
  }

  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // ********************** </do openmp> ***************************
  // ===============================================================

  // ===============================================================
  // ********************** < do cuda> *****************************
  // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

  // we will repeat the computation for each of the numbers of threads
  vector<unsigned int> threadsPerBlockArray;
  threadsPerBlockArray.push_back(32);
  threadsPerBlockArray.push_back(64);
  threadsPerBlockArray.push_back(128);
  threadsPerBlockArray.push_back(256);
  threadsPerBlockArray.push_back(512);

  printf("performing calculations with cuda\n");
  // for each number of threads per block
  for (const unsigned int numberOfThreadsPerBlock :
         threadsPerBlockArray) {

    double cudaIntegral = 0;
    // start timing
    tic = high_resolution_clock::now();

    // stop timing
    toc = high_resolution_clock::now();
    const double cudaElapsedTime =
      duration_cast<duration<double> >(toc - tic).count();

    // check the answer
    const double cudaRelativeError =
      std::abs(libraryAnswer - cudaIntegral) / std::abs(libraryAnswer);
    if (cudaRelativeError > 1e-3) {
      fprintf(stderr, "our answer is too far off: %15.8e instead of %15.8e\n",
              cudaIntegral, libraryAnswer);
      exit(1);
    }

    // output speedup
    printf("%3u : time %8.2e speedup %8.2e\n",
           numberOfThreadsPerBlock,
           cudaElapsedTime,
           fastSerialElapsedTime / cudaElapsedTime);
  }

  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // ********************** </do cuda> *****************************
  // ===============================================================

  // ===============================================================
  // ********************** < do kokkos> *****************************
  // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

  printf("performing calculations with kokkos on %s\n",
         typeid(Kokkos::DefaultExecutionSpace).name());

  Kokkos::initialize();

  const KokkosFunctor kokkosFunctor(dx);

  // start timing
  tic = high_resolution_clock::now();

  const double kokkosIntegral = 0;
  // TODO: calculate integral using kokkos

  // stop timing
  toc = high_resolution_clock::now();
  const double kokkosElapsedTime =
    duration_cast<duration<double> >(toc - tic).count();

  // check the answer
  const double kokkosRelativeError =
    std::abs(libraryAnswer - kokkosIntegral) / std::abs(libraryAnswer);
  if (kokkosRelativeError > 1e-3) {
    fprintf(stderr, "our answer is too far off: %15.8e instead of %15.8e\n",
            kokkosIntegral, libraryAnswer);
    exit(1);
  }

  // output speedup
  printf("kokkos : time %8.2e speedup %8.2e\n",
         kokkosElapsedTime,
         fastSerialElapsedTime / kokkosElapsedTime);

  Kokkos::finalize();

  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // ********************** </do kokkos> ***************************
  // ===============================================================

  return 0;
}
<|endoftext|>