<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "stx/io/filerepository.h"
#include "stx/io/fileutil.h"
#include "stx/application.h"
#include "stx/logging.h"
#include "stx/random.h"
#include "stx/thread/eventloop.h"
#include "stx/thread/threadpool.h"
#include "stx/thread/FixedSizeThreadPool.h"
#include "stx/wallclock.h"
#include "stx/VFS.h"
#include "stx/rpc/ServerGroup.h"
#include "stx/rpc/RPC.h"
#include "stx/rpc/RPCClient.h"
#include "stx/cli/flagparser.h"
#include "stx/json/json.h"
#include "stx/json/jsonrpc.h"
#include "stx/http/httprouter.h"
#include "stx/http/httpserver.h"
#include "stx/http/VFSFileServlet.h"
#include "brokerd/FeedService.h"
#include "brokerd/RemoteFeedFactory.h"
#include "brokerd/RemoteFeedReader.h"
#include "zbase/dproc/LocalScheduler.h"
#include "zbase/dproc/DispatchService.h"
#include "stx/stats/statsdagent.h"
#include "sstable/SSTableServlet.h"
#include "zbase/util/mdb/MDB.h"
#include "zbase/util/mdb/MDBUtil.h"
#include "zbase/AnalyticsServlet.h"
#include "zbase/WebUIServlet.h"
#include "zbase/ReportFactory.h"
#include "zbase/AnalyticsApp.h"
#include "zbase/EventIngress.h"
#include "zbase/TableDefinition.h"
#include "zbase/JoinedSession.pb.h"
#include "zbase/core/TSDBService.h"
#include "zbase/core/TSDBServlet.h"
#include "zbase/core/ReplicationWorker.h"
#include "zbase/DefaultServlet.h"
#include "csql/defaults.h"
#include "zbase/ConfigDirectory.h"

using namespace stx;
using namespace zbase;

stx::thread::EventLoop ev;

int main(int argc, const char** argv) {
  stx::Application::init();
  stx::Application::logToStderr();

  stx::cli::FlagParser flags;

  flags.defineFlag(
      "http_port",
      stx::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8080",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "frontend",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "frontend only?",
      "<switch>");

  flags.defineFlag(
      "cachedir",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "cachedir path",
      "<path>");

  flags.defineFlag(
      "datadir",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "datadir path",
      "<path>");

#ifndef ZBASE_HAS_ASSET_BUNDLE
  flags.defineFlag(
      "asset_path",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      "src/",
      "assets path",
      "<path>");
#endif

  flags.defineFlag(
      "indexbuild_threads",
      cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "2",
      "number of indexbuild threads",
      "<num>");

  flags.defineFlag(
      "master",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "url",
      "<addr>");

  flags.defineFlag(
      "replicate_to",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "url",
      "<addr>");

  flags.defineFlag(
      "loglevel",
      stx::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

#ifndef ZBASE_HAS_ASSET_BUNDLE
  Assets::setSearchPath(flags.getString("asset_path"));
#endif

  /* conf */
  //auto conf_data = FileUtil::read(flags.getString("conf"));
  //auto conf = msg::parseText<zbase::TSDBNodeConfig>(conf_data);

  /* thread pools */
  stx::thread::ThreadPool tpool;
  stx::thread::FixedSizeThreadPool wpool(8);
  wpool.start();

  /* http */
  stx::http::HTTPRouter http_router;
  stx::http::HTTPServer http_server(&http_router, &ev);
  http_server.listen(flags.getInt("http_port"));
  http::HTTPConnectionPool http(&ev);

  /* customer directory */
  auto cdb_dir = FileUtil::joinPaths(flags.getString("datadir"), "cdb");
  if (!FileUtil::exists(cdb_dir)) {
    FileUtil::mkdir(cdb_dir);
  }

  ConfigDirectory customer_dir(
      cdb_dir,
      InetAddr::resolve(flags.getString("master")),
      ConfigTopic::CUSTOMERS | ConfigTopic::TABLES | ConfigTopic::USERDB);

  /* dproc */
  auto local_scheduler = mkRef(
      new dproc::LocalScheduler(
          flags.getString("cachedir"),
          12));

  local_scheduler->start();

  /* DocumentDB */
  DocumentDB docdb(flags.getString("datadir"));

  /* tsdb */
  RefPtr<zbase::ReplicationScheme> repl_scheme;

  auto repl_targets = flags.getStrings("replicate_to");
  if (repl_targets.empty()) {
    repl_scheme = RefPtr<zbase::ReplicationScheme>(
        new zbase::StandaloneReplicationScheme());
  } else {
    Vector<zbase::ReplicaRef> replicas;

    for (const auto& r : repl_targets) {
      zbase::ReplicaRef rref(
          SHA1::compute(r),
          InetAddr::resolve(r));

      logInfo(
          "zbase",
          "Adding Remote Replica: $0 ($1)",
          rref.addr.hostAndPort(),
          rref.unique_id.toString());

      replicas.emplace_back(rref);
    }

    if (flags.isSet("frontend")) {
      repl_scheme = RefPtr<zbase::ReplicationScheme>(
          new zbase::FrontendReplicationScheme(replicas));
    } else {
      repl_scheme = RefPtr<zbase::ReplicationScheme>(
          new zbase::FixedReplicationScheme(replicas));
    }
  }

  auto tsdb_dir = FileUtil::joinPaths(flags.getString("datadir"), "tsdb");
  if (!FileUtil::exists(tsdb_dir)) {
    FileUtil::mkdir(tsdb_dir);
  }

  zbase::PartitionMap partition_map(tsdb_dir);
  zbase::TSDBService tsdb_node(&partition_map);
  zbase::ReplicationWorker tsdb_replication(
      repl_scheme.get(),
      &partition_map,
      &http);

  zbase::TSDBServlet tsdb_servlet(&tsdb_node, flags.getString("cachedir"));
  http_router.addRouteByPrefixMatch("/tsdb", &tsdb_servlet, &tpool);

  zbase::CSTableIndex cstable_index(
      &partition_map,
      flags.getInt("indexbuild_threads"));

  /* sql */
  auto sql = csql::Runtime::getDefaultRuntime();
  sql->setCacheDir(flags.getString("cachedir"));

  /* analytics core */
  AnalyticsAuth auth(&customer_dir);

  auto analytics_app = mkRef(
      new AnalyticsApp(
          &tsdb_node,
          &partition_map,
          repl_scheme.get(),
          &cstable_index,
          &customer_dir,
          &auth,
          sql.get(),
          flags.getString("datadir")));

  dproc::DispatchService dproc;
  dproc.registerApp(analytics_app.get(), local_scheduler.get());

  zbase::WebUIServlet webui_servlet(&auth);

  zbase::AnalyticsServlet analytics_servlet(
      analytics_app,
      &dproc,
      nullptr,
      flags.getString("cachedir"),
      &auth,
      sql.get(),
      &tsdb_node,
      &customer_dir,
      &docdb);

  zbase::DefaultServlet default_servlet;

  http_router.addRouteByPrefixMatch("/a/", &webui_servlet);
  http_router.addRouteByPrefixMatch("/api/", &analytics_servlet, &tpool);
  http_router.addRouteByPrefixMatch("/", &default_servlet);

  {
    FeedConfig fc;
    fc.set_customer("dawanda");
    fc.set_feed("search.ECommerceSearchQueriesFeed");
    fc.set_partition_size(kMicrosPerHour * 4);
    fc.set_first_partition(1430438400000000); // 2015-05-01 00:00:00Z
    fc.set_num_shards(128);
    fc.set_table_name("logjoin.joined_sessions");

    analytics_app->configureFeed(fc);
  }

  {
    FeedConfig fc;
    fc.set_customer("dawanda");
    fc.set_feed("reco_engine.ECommerceRecoQueriesFeed");
    fc.set_partition_size(kMicrosPerHour * 4);
    fc.set_first_partition(1432785600000000);
    fc.set_num_shards(32);
    fc.set_table_name("logjoin.joined_sessions");

    analytics_app->configureFeed(fc);
  }

  {
    FeedConfig fc;
    fc.set_customer("dawanda");
    fc.set_feed("reco_engine.ECommercePreferenceSetsFeed");
    fc.set_partition_size(kMicrosPerHour * 4);
    fc.set_first_partition(1430438400000000); // 2015-05-01 00:00:00Z
    fc.set_num_shards(32);
    fc.set_table_name("logjoin.joined_sessions");

    analytics_app->configureFeed(fc);
  }

  auto rusage_t = std::thread([] () {
    for (;; usleep(1000000)) {
      logDebug(
          "zbase",
          "Using $0MB of memory (peak $1)",
          Application::getCurrentMemoryUsage() / 1000000.0,
          Application::getPeakMemoryUsage() / 1000000.0);
    }
  });

  rusage_t.detach();

  try {
    partition_map.open();
    customer_dir.startWatcher();
    ev.run();
  } catch (const StandardException& e) {
    logAlert("zbase", e, "FATAL ERROR");
  }

  stx::logInfo("zbase", "Exiting...");

  local_scheduler->stop();
  customer_dir.stopWatcher();

  exit(0);
}

<commit_msg>add hack to allow to bump replica versions<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "stx/io/filerepository.h"
#include "stx/io/fileutil.h"
#include "stx/application.h"
#include "stx/logging.h"
#include "stx/random.h"
#include "stx/thread/eventloop.h"
#include "stx/thread/threadpool.h"
#include "stx/thread/FixedSizeThreadPool.h"
#include "stx/wallclock.h"
#include "stx/VFS.h"
#include "stx/rpc/ServerGroup.h"
#include "stx/rpc/RPC.h"
#include "stx/rpc/RPCClient.h"
#include "stx/cli/flagparser.h"
#include "stx/json/json.h"
#include "stx/json/jsonrpc.h"
#include "stx/http/httprouter.h"
#include "stx/http/httpserver.h"
#include "stx/http/VFSFileServlet.h"
#include "brokerd/FeedService.h"
#include "brokerd/RemoteFeedFactory.h"
#include "brokerd/RemoteFeedReader.h"
#include "zbase/dproc/LocalScheduler.h"
#include "zbase/dproc/DispatchService.h"
#include "stx/stats/statsdagent.h"
#include "sstable/SSTableServlet.h"
#include "zbase/util/mdb/MDB.h"
#include "zbase/util/mdb/MDBUtil.h"
#include "zbase/AnalyticsServlet.h"
#include "zbase/WebUIServlet.h"
#include "zbase/ReportFactory.h"
#include "zbase/AnalyticsApp.h"
#include "zbase/EventIngress.h"
#include "zbase/TableDefinition.h"
#include "zbase/JoinedSession.pb.h"
#include "zbase/core/TSDBService.h"
#include "zbase/core/TSDBServlet.h"
#include "zbase/core/ReplicationWorker.h"
#include "zbase/DefaultServlet.h"
#include "csql/defaults.h"
#include "zbase/ConfigDirectory.h"

using namespace stx;
using namespace zbase;

stx::thread::EventLoop ev;

int main(int argc, const char** argv) {
  stx::Application::init();
  stx::Application::logToStderr();

  stx::cli::FlagParser flags;

  flags.defineFlag(
      "http_port",
      stx::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8080",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "frontend",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "frontend only?",
      "<switch>");

  flags.defineFlag(
      "cachedir",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "cachedir path",
      "<path>");

  flags.defineFlag(
      "datadir",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "datadir path",
      "<path>");

#ifndef ZBASE_HAS_ASSET_BUNDLE
  flags.defineFlag(
      "asset_path",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      "src/",
      "assets path",
      "<path>");
#endif

  flags.defineFlag(
      "indexbuild_threads",
      cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "2",
      "number of indexbuild threads",
      "<num>");

  flags.defineFlag(
      "master",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "url",
      "<addr>");

  flags.defineFlag(
      "replicate_to",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "url",
      "<addr>");

  flags.defineFlag(
      "loglevel",
      stx::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

#ifndef ZBASE_HAS_ASSET_BUNDLE
  Assets::setSearchPath(flags.getString("asset_path"));
#endif

  /* conf */
  //auto conf_data = FileUtil::read(flags.getString("conf"));
  //auto conf = msg::parseText<zbase::TSDBNodeConfig>(conf_data);

  /* thread pools */
  stx::thread::ThreadPool tpool;
  stx::thread::FixedSizeThreadPool wpool(8);
  wpool.start();

  /* http */
  stx::http::HTTPRouter http_router;
  stx::http::HTTPServer http_server(&http_router, &ev);
  http_server.listen(flags.getInt("http_port"));
  http::HTTPConnectionPool http(&ev);

  /* customer directory */
  auto cdb_dir = FileUtil::joinPaths(flags.getString("datadir"), "cdb");
  if (!FileUtil::exists(cdb_dir)) {
    FileUtil::mkdir(cdb_dir);
  }

  ConfigDirectory customer_dir(
      cdb_dir,
      InetAddr::resolve(flags.getString("master")),
      ConfigTopic::CUSTOMERS | ConfigTopic::TABLES | ConfigTopic::USERDB);

  /* dproc */
  auto local_scheduler = mkRef(
      new dproc::LocalScheduler(
          flags.getString("cachedir"),
          12));

  local_scheduler->start();

  /* DocumentDB */
  DocumentDB docdb(flags.getString("datadir"));

  /* tsdb */
  RefPtr<zbase::ReplicationScheme> repl_scheme;

  auto repl_targets = flags.getStrings("replicate_to");
  if (repl_targets.empty()) {
    repl_scheme = RefPtr<zbase::ReplicationScheme>(
        new zbase::StandaloneReplicationScheme());
  } else {
    Vector<zbase::ReplicaRef> replicas;

    for (const auto& r : repl_targets) {
      auto addr = r;
      auto addr_end = StringUtil::find(addr, '+');
      if (addr_end != String::npos) {
        addr = addr.substr(0, addr_end);
      }

      zbase::ReplicaRef rref(
          SHA1::compute(r),
          InetAddr::resolve(addr));

      logInfo(
          "zbase",
          "Adding Remote Replica: $0 ($1)",
          rref.addr.hostAndPort(),
          rref.unique_id.toString());

      replicas.emplace_back(rref);
    }

    if (flags.isSet("frontend")) {
      repl_scheme = RefPtr<zbase::ReplicationScheme>(
          new zbase::FrontendReplicationScheme(replicas));
    } else {
      repl_scheme = RefPtr<zbase::ReplicationScheme>(
          new zbase::FixedReplicationScheme(replicas));
    }
  }

  auto tsdb_dir = FileUtil::joinPaths(flags.getString("datadir"), "tsdb");
  if (!FileUtil::exists(tsdb_dir)) {
    FileUtil::mkdir(tsdb_dir);
  }

  zbase::PartitionMap partition_map(tsdb_dir);
  zbase::TSDBService tsdb_node(&partition_map);
  zbase::ReplicationWorker tsdb_replication(
      repl_scheme.get(),
      &partition_map,
      &http);

  zbase::TSDBServlet tsdb_servlet(&tsdb_node, flags.getString("cachedir"));
  http_router.addRouteByPrefixMatch("/tsdb", &tsdb_servlet, &tpool);

  zbase::CSTableIndex cstable_index(
      &partition_map,
      flags.getInt("indexbuild_threads"));

  /* sql */
  auto sql = csql::Runtime::getDefaultRuntime();
  sql->setCacheDir(flags.getString("cachedir"));

  /* analytics core */
  AnalyticsAuth auth(&customer_dir);

  auto analytics_app = mkRef(
      new AnalyticsApp(
          &tsdb_node,
          &partition_map,
          repl_scheme.get(),
          &cstable_index,
          &customer_dir,
          &auth,
          sql.get(),
          flags.getString("datadir")));

  dproc::DispatchService dproc;
  dproc.registerApp(analytics_app.get(), local_scheduler.get());

  zbase::WebUIServlet webui_servlet(&auth);

  zbase::AnalyticsServlet analytics_servlet(
      analytics_app,
      &dproc,
      nullptr,
      flags.getString("cachedir"),
      &auth,
      sql.get(),
      &tsdb_node,
      &customer_dir,
      &docdb);

  zbase::DefaultServlet default_servlet;

  http_router.addRouteByPrefixMatch("/a/", &webui_servlet);
  http_router.addRouteByPrefixMatch("/api/", &analytics_servlet, &tpool);
  http_router.addRouteByPrefixMatch("/", &default_servlet);

  {
    FeedConfig fc;
    fc.set_customer("dawanda");
    fc.set_feed("search.ECommerceSearchQueriesFeed");
    fc.set_partition_size(kMicrosPerHour * 4);
    fc.set_first_partition(1430438400000000); // 2015-05-01 00:00:00Z
    fc.set_num_shards(128);
    fc.set_table_name("logjoin.joined_sessions");

    analytics_app->configureFeed(fc);
  }

  {
    FeedConfig fc;
    fc.set_customer("dawanda");
    fc.set_feed("reco_engine.ECommerceRecoQueriesFeed");
    fc.set_partition_size(kMicrosPerHour * 4);
    fc.set_first_partition(1432785600000000);
    fc.set_num_shards(32);
    fc.set_table_name("logjoin.joined_sessions");

    analytics_app->configureFeed(fc);
  }

  {
    FeedConfig fc;
    fc.set_customer("dawanda");
    fc.set_feed("reco_engine.ECommercePreferenceSetsFeed");
    fc.set_partition_size(kMicrosPerHour * 4);
    fc.set_first_partition(1430438400000000); // 2015-05-01 00:00:00Z
    fc.set_num_shards(32);
    fc.set_table_name("logjoin.joined_sessions");

    analytics_app->configureFeed(fc);
  }

  auto rusage_t = std::thread([] () {
    for (;; usleep(1000000)) {
      logDebug(
          "zbase",
          "Using $0MB of memory (peak $1)",
          Application::getCurrentMemoryUsage() / 1000000.0,
          Application::getPeakMemoryUsage() / 1000000.0);
    }
  });

  rusage_t.detach();

  try {
    partition_map.open();
    customer_dir.startWatcher();
    ev.run();
  } catch (const StandardException& e) {
    logAlert("zbase", e, "FATAL ERROR");
  }

  stx::logInfo("zbase", "Exiting...");

  local_scheduler->stop();
  customer_dir.stopWatcher();

  exit(0);
}

<|endoftext|>


<commit_before>/* Comic Sailor - Peebles Lab */
#include <stdio.h>
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"

char peebles_baseurl[] = "http://www.peebleslab.com/";
char peebles_license[] = "http://creativecommons.org/licenses/by-nc-sa/3.0/us/";

// helper functions
extern int getcurldata(char *url, struct curl_inputstruct *chunk);
extern char *fillstring(char *ptr, char *beg, int nr, char *end);

// return the url for newest comic - fill in struct Selectedcomic_data
int Selectedcomic::peebleslab_getcurrent() {

// for init

if (newest == 0) {
	// step 0: DON'T CHECK FOR CURRENT.
	// Peebleslab probably won't update anymore, the latest is #100 from Jan 17th, 2011.
	// We could parse the website source for "Latest" to be sure. We won't.
	newest = 100;
	current = 100;
	char img[] = "http://www.peebleslab.com/comics/100.png\0";
	current_url = fillstring(current_url, peebles_baseurl, (long int) NULL, (char *) NULL);
	current_img = fillstring(current_img, img, (long int) NULL, (char *) NULL);

	// we could do this, but it's not needed since we do a static init
	//peebleslab_changecurrent(data, newest);
	//printf("peebleslab newest nr is %d and url and img  are %s / %s\n",newest, current_url, current_img);
	}
	else {
	current_url = fillstring(current_url, peebles_baseurl, current, (char *)NULL);
	}

	// current_img
	// create an url of the form: http://peebleslab.com/nr.png
	char img_beg[] = "http://www.peebleslab.com/comics/";
	char img_end[] = ".png\0";
	char img_current[5] = "";
	free (current_img);
	current_img = (char *) malloc(strlen(img_beg) + strlen(img_end) + 5 + 1 ); // 5 = img_current
	sprintf(img_current, "%d", current);
	strncat(current_img, img_beg, strlen(img_beg));
	strncat(current_img, img_current, strlen(img_current));
	strncat(current_img, img_end, strlen(img_end));

	//printf("full img url is %s\n", current_img);
	return 1;
	}
<commit_msg>Fully functional Peebles Lab. Note that fully functional means the static comics 1-100, we won't be checking for updates.<commit_after>/* Comic Sailor - Peebles Lab */
#include <stdio.h>
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"

char peebles_baseurl[] = "http://www.peebleslab.com/";
char peebles_license[] = "http://creativecommons.org/licenses/by-nc-sa/3.0/us/";

// helper functions
extern char *fillstring(char *ptr, char *beg, int nr, char *end);

// return the url for newest comic - fill in struct Selectedcomic_data
int Selectedcomic::peebleslab_getcurrent() {

    // for init

    if (newest == 0) {
        // step 0: DON'T CHECK FOR CURRENT.
        // Peebleslab probably won't update anymore, the latest is #100 from Jan 17th, 2011.
        // We could parse the website source for "Latest" to be sure. We won't.
        newest = 100;
        current = 100;
        char img[] = "http://www.peebleslab.com/comics/100.png\0";
        current_url = fillstring(current_url, peebles_baseurl, (long int) NULL, (char *) NULL);
        current_img = fillstring(current_img, img, (long int) NULL, (char *) NULL);

        // we could do this, but it's not needed since we do a static init
        //peebleslab_changecurrent(data, newest);
        }
	else {
        current_url = fillstring(current_url, peebles_baseurl, current, (char *)NULL);
        }

    // current_img
	// create an url of the form: http://peebleslab.com/nr.png
    char img_beg[] = "http://www.peebleslab.com/comics/";
    char img_end[] = ".png";
    fillstring(current_img, img_beg, current, img_end);
    return 1;
    }
<|endoftext|>


<commit_before>///
/// @file  pi_lmo1.cpp
/// @brief Simple implementation of the Lagarias-Miller-Odlyzko prime
///        counting algorithm. This implementation does not use
///        segmentation to calculate S2(x) and the calculation of phi
///        in S2(x) does not use a special data structure which counts
///        the number of unsieved elements in O(log N) operations.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include "PhiTiny.hpp"
#include "PhiCache.hpp"
#include "pmath.hpp"
#include "Pk.hpp"

#include <primecount.hpp>
#include <primesieve.hpp>
#include <stdint.h>
#include <vector>

using namespace primecount;

namespace {

/// Calculate the contribution of the ordinary leaves.
///
int64_t S1(int64_t x,
           int64_t x13_alpha,
           int64_t c,
           std::vector<int32_t>& primes,
           std::vector<int32_t>& lpf,
           std::vector<int32_t>& mu)
{
  int64_t S1_result = 0;

  const PhiTiny phiTiny;
  PhiCache cache(primes, phiTiny);

  for (int64_t n = 1; n <= x13_alpha; n++)
    if (lpf[n] > primes[c])
      S1_result += mu[n] * phi(x / n, c, &cache);

  return S1_result;
}

/// Calculate the contribution of the special leaves.
///
int64_t S2(int64_t x,
           int64_t x13_alpha,
           int64_t a,
           int64_t c,
           double alpha,
           std::vector<int32_t>& primes,
           std::vector<int32_t>& lpf,
           std::vector<int32_t>& mu)
{
  int64_t x23 = (int64_t) std::pow((double) x / alpha, 2.0 / 3.0);
  int64_t S2_result = 0;

  std::vector<char> sieve(x23 + 1, 1);

  // phi(y, b) nodes with b <= c do not contribute to S2, so we
  // simply sieve out the multiples of the first c primes
  //
  for (int64_t b = 1; b <= c; b++)
  {
    int64_t prime = primes[b];
    for (int64_t i = prime; i <= x23; i += prime)
      sieve[i] = 0;
  }

  for (int64_t b = c; b < a; b++)
  {
    int64_t prime = primes[b + 1];
    int64_t phi = 0;
    int64_t old = 0;

    for (int64_t m = x13_alpha; m > x13_alpha / prime; m--)
    {
      if (mu[m] != 0 && prime < lpf[m])
      {
        // We have found a special leaf, compute it's contribution
        // phi(x / (m * primes[b + 1]), b) by counting the
        // number of unsieved elements below x / (m * primes[b + 1])
        // after having removed the multiples of the first b primes
        //
        int64_t q = x / (m * prime);
        for (int64_t k = old + 1; k <= q; k++)
          phi += sieve[k];
        old = q;
        S2_result -= mu[m] * phi;
      }
    }

    assert(prime > 2);
    // Remove the multiples of (b + 1)th prime
    for (int64_t i = prime; i <= x23; i += prime * 2)
      sieve[i] = 0;
  }

  return S2_result;
}

} // namespace

namespace primecount {

/// Calculate the number of primes below x using the
/// Lagarias-Miller-Odlyzko algorithm.
/// Run time: O(x^(2/3)) operations, O(x^(2/3)) space.
/// @note O(x^(2/3)) space is because S2(x, c) is not segmented.
///
int64_t pi_lmo1(int64_t x, int threads)
{
  if (x < 2)
    return 0;

  // Optimization factor, see:
  // Tomás Oliveira e Silva, Computing pi(x): the combinatorial method,
  // Revista do DETUA, vol. 4, no. 6, pp. 759-768, March 2006.
  double beta = 1.1;
  double alpha = std::max(1.0, nth_log<2>(x) * beta);

  int64_t x13 = iroot<3>(x);
  int64_t x13_alpha = (int64_t)(x13 * alpha);
  int64_t a = pi_lehmer(x13_alpha);
  int64_t c = (a < 6) ? a : 6;

  std::vector<int32_t> primes;
  std::vector<int32_t> lpf = make_least_prime_factor(x13_alpha);
  std::vector<int32_t> mu = make_moebius(x13_alpha);

  primes.push_back(0);
  primesieve::generate_n_primes(a, &primes);

  int64_t phi = S1(x, x13_alpha, c, primes, lpf , mu) + S2(x, x13_alpha, a, c, alpha, primes, lpf , mu);
  int64_t sum = phi + a - 1 - P2(x, a, threads);

  return sum;
}

} // namespace primecount
<commit_msg>Refactoring<commit_after>///
/// @file  pi_lmo1.cpp
/// @brief Simple implementation of the Lagarias-Miller-Odlyzko prime
///        counting algorithm. This implementation does not use
///        segmentation to calculate S2(x) and the calculation of phi
///        in S2(x) does not use a special data structure which counts
///        the number of unsieved elements in O(log N) operations.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include "PhiTiny.hpp"
#include "PhiCache.hpp"
#include "pmath.hpp"
#include "Pk.hpp"

#include <primecount.hpp>
#include <primesieve.hpp>
#include <stdint.h>
#include <vector>

using namespace primecount;

namespace {

/// Calculate the contribution of the ordinary leaves.
///
int64_t S1(int64_t x,
           int64_t x13_alpha,
           int64_t c,
           std::vector<int32_t>& primes,
           std::vector<int32_t>& lpf,
           std::vector<int32_t>& mu)
{
  int64_t S1_result = 0;

  const PhiTiny phiTiny;
  PhiCache cache(primes, phiTiny);

  for (int64_t n = 1; n <= x13_alpha; n++)
    if (lpf[n] > primes[c])
      S1_result += mu[n] * phi(x / n, c, &cache);

  return S1_result;
}

/// Calculate the contribution of the special leaves.
///
int64_t S2(int64_t x,
           int64_t x13_alpha,
           int64_t x23_alpha,
           int64_t a,
           int64_t c,
           std::vector<int32_t>& primes,
           std::vector<int32_t>& lpf,
           std::vector<int32_t>& mu)
{
  int64_t S2_result = 0;
  std::vector<char> sieve(x23_alpha + 1, 1);

  // phi(y, b) nodes with b <= c do not contribute to S2, so we
  // simply sieve out the multiples of the first c primes
  //
  for (int64_t b = 1; b <= c; b++)
  {
    int64_t prime = primes[b];
    for (int64_t i = prime; i <= x23_alpha; i += prime)
      sieve[i] = 0;
  }

  for (int64_t b = c; b < a; b++)
  {
    int64_t prime = primes[b + 1];
    int64_t phi = 0;
    int64_t old = 0;

    for (int64_t m = x13_alpha; m > x13_alpha / prime; m--)
    {
      if (mu[m] != 0 && prime < lpf[m])
      {
        // We have found a special leaf, compute it's contribution
        // phi(x / (m * primes[b + 1]), b) by counting the
        // number of unsieved elements below x / (m * primes[b + 1])
        // after having removed the multiples of the first b primes
        //
        int64_t q = x / (m * prime);
        for (int64_t k = old + 1; k <= q; k++)
          phi += sieve[k];
        old = q;
        S2_result -= mu[m] * phi;
      }
    }

    assert(prime > 2);
    // Remove the multiples of (b + 1)th prime
    for (int64_t i = prime; i <= x23_alpha; i += prime * 2)
      sieve[i] = 0;
  }

  return S2_result;
}

} // namespace

namespace primecount {

/// Calculate the number of primes below x using the
/// Lagarias-Miller-Odlyzko algorithm.
/// Run time: O(x^(2/3)) operations, O(x^(2/3)) space.
/// @note O(x^(2/3)) space is because S2(x, c) is not segmented.
///
int64_t pi_lmo1(int64_t x, int threads)
{
  if (x < 2)
    return 0;

  // Optimization factor, see:
  // Tomás Oliveira e Silva, Computing pi(x): the combinatorial method,
  // Revista do DETUA, vol. 4, no. 6, pp. 759-768, March 2006.
  double beta = 1.1;
  double alpha = std::max(1.0, nth_log<2>(x) * beta);

  int64_t x13 = iroot<3>(x);
  int64_t x13_alpha = (int64_t)(x13 * alpha);
  int64_t x23_alpha = (int64_t) std::pow((double) x / alpha, 2.0 / 3.0);
  int64_t a = pi_lehmer(x13_alpha);
  int64_t c = (a < 6) ? a : 6;

  std::vector<int32_t> primes;
  std::vector<int32_t> lpf = make_least_prime_factor(x13_alpha);
  std::vector<int32_t> mu = make_moebius(x13_alpha);

  primes.push_back(0);
  primesieve::generate_n_primes(a, &primes);

  int64_t phi = S1(x, x13_alpha, c, primes, lpf , mu) + S2(x, x13_alpha, x23_alpha, a, c, primes, lpf , mu);
  int64_t sum = phi + a - 1 - P2(x, a, threads);

  return sum;
}

} // namespace primecount
<|endoftext|>


<commit_before>#include <cppunit/Portability.h>
#include <cppunit/Test.h>
#include <cppunit/TestPath.h>
#include <stdexcept>

CPPUNIT_NS_BEGIN

TestPath::TestPath()
{
}

TestPath::TestPath( Test *root )
{
  add( root );
}

TestPath::TestPath( const TestPath &other,
                    int indexFirst,
                    int count )
{
  int countAdjustment = 0;
  if ( indexFirst < 0 )
  {
    countAdjustment = indexFirst;
    indexFirst = 0;
  }

  if ( count < 0 )
    count = other.getTestCount();
  else
    count += countAdjustment;

  int index = indexFirst;
  while ( count-- > 0  &&  index < other.getTestCount() )
    add( other.getTestAt( index++ ) );
}

TestPath::TestPath( Test *searchRoot,
                    const std::string &pathAsString )
{
  PathTestNames testNames;

  Test *parentTest = findActualRoot( searchRoot, pathAsString, testNames );
  add( parentTest );

  for ( unsigned int index = 1; index < testNames.size(); ++index )
  {
    bool childFound = false;
    for ( int childIndex =0; childIndex < parentTest->getChildTestCount(); ++childIndex )
    {
      if ( parentTest->getChildTestAt( childIndex )->getName() == testNames[index] )
      {
        childFound = true;
        parentTest = parentTest->getChildTestAt( childIndex );
        break;
      }
    }

    if ( !childFound )
      throw std::invalid_argument( "TestPath::TestPath(): failed to resolve test name <"+
                                   testNames[index] + "> of path <" + pathAsString + ">" );

    add( parentTest );
  }
}

TestPath::TestPath( const TestPath &other )
  : m_tests( other.m_tests )
{
}

TestPath::~TestPath()
{
}

TestPath &
TestPath::operator =( const TestPath &other )
{
  if ( &other != this )
    m_tests = other.m_tests;
  return *this;
}

bool
TestPath::isValid() const
{
  return getTestCount() > 0;
}

void
TestPath::add( Test *test )
{
  m_tests.push_back( test );
}

void
TestPath::add( const TestPath &path )
{
  for ( int index =0; index < path.getTestCount(); ++index )
    add( path.getTestAt( index ) );
}

void
TestPath::insert( Test *test,
                  int index )
{
  if ( index < 0  ||  index > getTestCount() )
    throw std::out_of_range( "TestPath::insert(): index out of range" );
  m_tests.insert( m_tests.begin() + index, test );
}

void
TestPath::insert( const TestPath &path,
                  int index )
{
  int itemIndex = path.getTestCount() -1;
  while ( itemIndex >= 0 )
    insert( path.getTestAt( itemIndex-- ), index );
}

void
TestPath::removeTests()
{
  while ( isValid() )
    removeTest( 0 );
}

void
TestPath::removeTest( int index )
{
  checkIndexValid( index );
  m_tests.erase( m_tests.begin() + index );
}

void
TestPath::up()
{
  checkIndexValid( 0 );
  removeTest( getTestCount() -1 );
}

int
TestPath::getTestCount() const
{
  return m_tests.size();
}

Test *
TestPath::getTestAt( int index ) const
{
  checkIndexValid( index );
  return m_tests[index];
}

Test *
TestPath::getChildTest() const
{
  return getTestAt( getTestCount() -1 );
}

void
TestPath::checkIndexValid( int index ) const
{
  if ( index < 0  ||  index >= getTestCount() )
    throw std::out_of_range( "TestPath::checkIndexValid(): index out of range" );
}

std::string
TestPath::toString() const
{
  std::string asString( "/" );
  for ( int index =0; index < getTestCount(); ++index )
  {
    if ( index > 0 )
      asString += '/';
    asString += getTestAt(index)->getName();
  }

  return asString;
}

Test *
TestPath::findActualRoot( Test *searchRoot,
                          const std::string &pathAsString,
                          PathTestNames &testNames )
{
  bool isRelative = splitPathString( pathAsString, testNames );

  if ( isRelative  &&  pathAsString.empty() )
    return searchRoot;

  if ( testNames.empty() )
    throw std::invalid_argument( "TestPath::TestPath(): invalid root or root name in absolute path" );

  Test *root = isRelative ? searchRoot->findTest( testNames[0] )  // throw if bad test name
                          : searchRoot;
  if ( root->getName() != testNames[0] )
    throw std::invalid_argument( "TestPath::TestPath(): searchRoot does not match path root name" );

  return root;
}

bool
TestPath::splitPathString( const std::string &pathAsString,
                           PathTestNames &testNames )
{
  bool isRelative = pathAsString.length()  &&  pathAsString[0] != "/";

  int index = (isRelative ? 0 : 1);
  while ( true )
  {
    int separatorIndex = pathAsString.find( '/', index );
    if ( separatorIndex >= 0 )
    {
      testNames.push_back( pathAsString.substr( index, separatorIndex - index ) );
      index = separatorIndex + 1;
    }
    else
    {
      testNames.push_back( pathAsString.substr( index ) );
      break;
    }
  }

  return isRelative;
}

CPPUNIT_NS_END
<commit_msg>src/cppunit/TestPath.cpp: bug #938753, array bound read in splitPathString() with substr if an empty string is passed.<commit_after>#include <cppunit/Portability.h>
#include <cppunit/Test.h>
#include <cppunit/TestPath.h>
#include <stdexcept>

CPPUNIT_NS_BEGIN

TestPath::TestPath()
{
}

TestPath::TestPath( Test *root )
{
  add( root );
}

TestPath::TestPath( const TestPath &other,
                    int indexFirst,
                    int count )
{
  int countAdjustment = 0;
  if ( indexFirst < 0 )
  {
    countAdjustment = indexFirst;
    indexFirst = 0;
  }

  if ( count < 0 )
    count = other.getTestCount();
  else
    count += countAdjustment;

  int index = indexFirst;
  while ( count-- > 0  &&  index < other.getTestCount() )
    add( other.getTestAt( index++ ) );
}

TestPath::TestPath( Test *searchRoot,
                    const std::string &pathAsString )
{
  PathTestNames testNames;

  Test *parentTest = findActualRoot( searchRoot, pathAsString, testNames );
  add( parentTest );

  for ( unsigned int index = 1; index < testNames.size(); ++index )
  {
    bool childFound = false;
    for ( int childIndex =0; childIndex < parentTest->getChildTestCount(); ++childIndex )
    {
      if ( parentTest->getChildTestAt( childIndex )->getName() == testNames[index] )
      {
        childFound = true;
        parentTest = parentTest->getChildTestAt( childIndex );
        break;
      }
    }

    if ( !childFound )
      throw std::invalid_argument( "TestPath::TestPath(): failed to resolve test name <"+
                                   testNames[index] + "> of path <" + pathAsString + ">" );

    add( parentTest );
  }
}

TestPath::TestPath( const TestPath &other )
  : m_tests( other.m_tests )
{
}

TestPath::~TestPath()
{
}

TestPath &
TestPath::operator =( const TestPath &other )
{
  if ( &other != this )
    m_tests = other.m_tests;
  return *this;
}

bool
TestPath::isValid() const
{
  return getTestCount() > 0;
}

void
TestPath::add( Test *test )
{
  m_tests.push_back( test );
}

void
TestPath::add( const TestPath &path )
{
  for ( int index =0; index < path.getTestCount(); ++index )
    add( path.getTestAt( index ) );
}

void
TestPath::insert( Test *test,
                  int index )
{
  if ( index < 0  ||  index > getTestCount() )
    throw std::out_of_range( "TestPath::insert(): index out of range" );
  m_tests.insert( m_tests.begin() + index, test );
}

void
TestPath::insert( const TestPath &path,
                  int index )
{
  int itemIndex = path.getTestCount() -1;
  while ( itemIndex >= 0 )
    insert( path.getTestAt( itemIndex-- ), index );
}

void
TestPath::removeTests()
{
  while ( isValid() )
    removeTest( 0 );
}

void
TestPath::removeTest( int index )
{
  checkIndexValid( index );
  m_tests.erase( m_tests.begin() + index );
}

void
TestPath::up()
{
  checkIndexValid( 0 );
  removeTest( getTestCount() -1 );
}

int
TestPath::getTestCount() const
{
  return m_tests.size();
}

Test *
TestPath::getTestAt( int index ) const
{
  checkIndexValid( index );
  return m_tests[index];
}

Test *
TestPath::getChildTest() const
{
  return getTestAt( getTestCount() -1 );
}

void
TestPath::checkIndexValid( int index ) const
{
  if ( index < 0  ||  index >= getTestCount() )
    throw std::out_of_range( "TestPath::checkIndexValid(): index out of range" );
}

std::string
TestPath::toString() const
{
  std::string asString( "/" );
  for ( int index =0; index < getTestCount(); ++index )
  {
    if ( index > 0 )
      asString += '/';
    asString += getTestAt(index)->getName();
  }

  return asString;
}

Test *
TestPath::findActualRoot( Test *searchRoot,
                          const std::string &pathAsString,
                          PathTestNames &testNames )
{
  bool isRelative = splitPathString( pathAsString, testNames );

  if ( isRelative  &&  pathAsString.empty() )
    return searchRoot;

  if ( testNames.empty() )
    throw std::invalid_argument( "TestPath::TestPath(): invalid root or root name in absolute path" );

  Test *root = isRelative ? searchRoot->findTest( testNames[0] )  // throw if bad test name
                          : searchRoot;
  if ( root->getName() != testNames[0] )
    throw std::invalid_argument( "TestPath::TestPath(): searchRoot does not match path root name" );

  return root;
}

bool
TestPath::splitPathString( const std::string &pathAsString,
                           PathTestNames &testNames )
{
  bool isRelative = pathAsString.length()  &&  pathAsString[0] != '/';

  int index = (isRelative ? 0 : 1);
  while ( true )
  {
    int separatorIndex = pathAsString.find( '/', index );
    if ( separatorIndex >= 0 )
    {
      testNames.push_back( pathAsString.substr( index, separatorIndex - index ) );
      index = separatorIndex + 1;
    }
    else
    {
      testNames.push_back( pathAsString.substr( index ) );
      break;
    }
  }

  return isRelative;
}

CPPUNIT_NS_END
<|endoftext|>


<commit_before>/*
 *  synchtimer.cpp  -  timers which synchronize to time boundaries
 *  Program:  kalarm
 *  Copyright © 2004,2005,2007,2008 by David Jarvie <djarvie@kde.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "kalarm.h"
#include <QTimer>
#include <kdebug.h>
#include "synchtimer.moc"

/*=============================================================================
=  Class: SynchTimer
=  Virtual base class for application-wide timer synchronized to a time boundary.
=============================================================================*/

SynchTimer::SynchTimer()
{
	mTimer = new QTimer(this);
	mTimer->setSingleShot(true);
}

SynchTimer::~SynchTimer()
{
	delete mTimer;
	mTimer = 0;
}

/******************************************************************************
* Connect to the timer. The timer is started if necessary.
*/
void SynchTimer::connecT(QObject* receiver, const char* member)
{
	Connection connection(receiver, member);
	if (mConnections.contains(connection))
		return;           // the slot is already connected, so ignore request
	connect(mTimer, SIGNAL(timeout()), receiver, member);
	mConnections.append(connection);
	if (!mTimer->isActive())
	{
		connect(mTimer, SIGNAL(timeout()), this, SLOT(slotTimer()));
		start();
	}
}

/******************************************************************************
* Disconnect from the timer. The timer is stopped if no longer needed.
*/
void SynchTimer::disconnecT(QObject* receiver, const char* member)
{
	if (mTimer)
	{
		mTimer->disconnect(receiver, member);
		if (member)
		{
			mConnections.removeAt(mConnections.indexOf(Connection(receiver, member)));
		}
		else
		{
			for (int i = 0;  i < mConnections.count();  )
			{
				if (mConnections[i].receiver == receiver)
					mConnections.removeAt(i);
				else
					++i;
			}
		}
		if (mConnections.isEmpty())
		{
			mTimer->disconnect();
			mTimer->stop();
		}
	}
}

/*=============================================================================
=  Class: MinuteTimer
=  Application-wide timer synchronized to the minute boundary.
=============================================================================*/

MinuteTimer* MinuteTimer::mInstance = 0;

MinuteTimer* MinuteTimer::instance()
{
	if (!mInstance)
		mInstance = new MinuteTimer;
	return mInstance;
}

/******************************************************************************
* Called when the timer triggers, or to start the timer.
* Timers can under some circumstances wander off from the correct trigger time,
* so rather than setting a 1 minute interval, calculate the correct next
* interval each time it triggers.
*/
void MinuteTimer::slotTimer()
{
	kDebug();
	int interval = 62 - QTime::currentTime().second();
	mTimer->start(interval * 1000);     // execute a single shot
}

/*=============================================================================
=  Class: DailyTimer
=  Application-wide timer synchronized to midnight.
=============================================================================*/

QList<DailyTimer*> DailyTimer::mFixedTimers;

DailyTimer::DailyTimer(const QTime& timeOfDay, bool fixed)
	: mTime(timeOfDay),
	  mFixed(fixed)
{
	if (fixed)
		mFixedTimers.append(this);
}

DailyTimer::~DailyTimer()
{
	if (mFixed)
		mFixedTimers.removeAt(mFixedTimers.indexOf(this));
}

DailyTimer* DailyTimer::fixedInstance(const QTime& timeOfDay, bool create)
{
	for (int i = 0, end = mFixedTimers.count();  i < end;  ++i)
		if (mFixedTimers[i]->mTime == timeOfDay)
			return mFixedTimers[i];
	return create ? new DailyTimer(timeOfDay, true) : 0;
}

/******************************************************************************
* Disconnect from the timer signal which triggers at the given fixed time of day.
* If there are no remaining connections to that timer, it is destroyed.
*/
void DailyTimer::disconnect(const QTime& timeOfDay, QObject* receiver, const char* member)
{
	DailyTimer* timer = fixedInstance(timeOfDay, false);
	if (!timer)
		return;
	timer->disconnecT(receiver, member);
	if (!timer->hasConnections())
		delete timer;
}

/******************************************************************************
* Change the time at which the variable timer triggers.
*/
void DailyTimer::changeTime(const QTime& newTimeOfDay, bool triggerMissed)
{
	if (mFixed)
		return;
	if (mTimer->isActive())
	{
		mTimer->stop();
		bool triggerNow = false;
		if (triggerMissed)
		{
			QTime now = QTime::currentTime();
			if (now >= newTimeOfDay  &&  now < mTime)
			{
				// The trigger time is now earlier and it has already arrived today.
				// Trigger a timer event immediately.
				triggerNow = true;
			}
		}
		mTime = newTimeOfDay;
		if (triggerNow)
			mTimer->start(0);    // trigger immediately
		else
			start();
	}
	else
		mTime = newTimeOfDay;
}

/******************************************************************************
* Initialise the timer to trigger at the specified time.
* This will either be today or tomorrow, depending on whether the trigger time
* has already passed.
*/
void DailyTimer::start()
{
	// TIMEZONE = local time
	QDateTime now = QDateTime::currentDateTime();
	// Find out whether to trigger today or tomorrow.
	// In preference, use the last trigger date to determine this, since
	// that will avoid possible errors due to daylight savings time changes.
	bool today;
	if (mLastDate.isValid())
		today = (mLastDate < now.date());
	else
		today = (now.time() < mTime);
	QDateTime next;
	if (today)
		next = QDateTime(now.date(), mTime);
	else
		next = QDateTime(now.date().addDays(1), mTime);
	uint interval = next.toTime_t() - now.toTime_t();
	mTimer->start(interval * 1000);    // execute a single shot
	kDebug() << "at" << mTime.hour() << ":" << mTime.minute() << ": interval =" << interval/3600 << ":" << (interval/60)%60 << ":" << interval%60;
}

/******************************************************************************
* Called when the timer triggers.
* Set the timer to trigger again tomorrow at the specified time.
* Note that if daylight savings time changes occur, this will not be 24 hours
* from now.
*/
void DailyTimer::slotTimer()
{
	// TIMEZONE = local time
	QDateTime now = QDateTime::currentDateTime();
	mLastDate = now.date();
	QDateTime next = QDateTime(mLastDate.addDays(1), mTime);
	uint interval = next.toTime_t() - now.toTime_t();
	mTimer->start(interval * 1000);    // execute a single shot
	kDebug() << "at" << mTime.hour() << ":" << mTime.minute() << ": interval =" << interval/3600 << ":" << (interval/60)%60 << ":" << interval%60;
}
<commit_msg>Fix disconnect() of non-existent timer<commit_after>/*
 *  synchtimer.cpp  -  timers which synchronize to time boundaries
 *  Program:  kalarm
 *  Copyright © 2004,2005,2007-2009 by David Jarvie <djarvie@kde.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "kalarm.h"
#include <QTimer>
#include <kdebug.h>
#include "synchtimer.moc"

/*=============================================================================
=  Class: SynchTimer
=  Virtual base class for application-wide timer synchronized to a time boundary.
=============================================================================*/

SynchTimer::SynchTimer()
{
	mTimer = new QTimer(this);
	mTimer->setSingleShot(true);
}

SynchTimer::~SynchTimer()
{
	delete mTimer;
	mTimer = 0;
}

/******************************************************************************
* Connect to the timer. The timer is started if necessary.
*/
void SynchTimer::connecT(QObject* receiver, const char* member)
{
	Connection connection(receiver, member);
	if (mConnections.contains(connection))
		return;           // the slot is already connected, so ignore request
	connect(mTimer, SIGNAL(timeout()), receiver, member);
	mConnections.append(connection);
	if (!mTimer->isActive())
	{
		connect(mTimer, SIGNAL(timeout()), this, SLOT(slotTimer()));
		start();
	}
}

/******************************************************************************
* Disconnect from the timer. The timer is stopped if no longer needed.
*/
void SynchTimer::disconnecT(QObject* receiver, const char* member)
{
	if (mTimer)
	{
		mTimer->disconnect(receiver, member);
		if (member)
		{
			int i = mConnections.indexOf(Connection(receiver, member));
			if (i >= 0)
				mConnections.removeAt(i);
		}
		else
		{
			for (int i = 0;  i < mConnections.count();  )
			{
				if (mConnections[i].receiver == receiver)
					mConnections.removeAt(i);
				else
					++i;
			}
		}
		if (mConnections.isEmpty())
		{
			mTimer->disconnect();
			mTimer->stop();
		}
	}
}

/*=============================================================================
=  Class: MinuteTimer
=  Application-wide timer synchronized to the minute boundary.
=============================================================================*/

MinuteTimer* MinuteTimer::mInstance = 0;

MinuteTimer* MinuteTimer::instance()
{
	if (!mInstance)
		mInstance = new MinuteTimer;
	return mInstance;
}

/******************************************************************************
* Called when the timer triggers, or to start the timer.
* Timers can under some circumstances wander off from the correct trigger time,
* so rather than setting a 1 minute interval, calculate the correct next
* interval each time it triggers.
*/
void MinuteTimer::slotTimer()
{
	kDebug();
	int interval = 62 - QTime::currentTime().second();
	mTimer->start(interval * 1000);     // execute a single shot
}

/*=============================================================================
=  Class: DailyTimer
=  Application-wide timer synchronized to midnight.
=============================================================================*/

QList<DailyTimer*> DailyTimer::mFixedTimers;

DailyTimer::DailyTimer(const QTime& timeOfDay, bool fixed)
	: mTime(timeOfDay),
	  mFixed(fixed)
{
	if (fixed)
		mFixedTimers.append(this);
}

DailyTimer::~DailyTimer()
{
	if (mFixed)
		mFixedTimers.removeAt(mFixedTimers.indexOf(this));
}

DailyTimer* DailyTimer::fixedInstance(const QTime& timeOfDay, bool create)
{
	for (int i = 0, end = mFixedTimers.count();  i < end;  ++i)
		if (mFixedTimers[i]->mTime == timeOfDay)
			return mFixedTimers[i];
	return create ? new DailyTimer(timeOfDay, true) : 0;
}

/******************************************************************************
* Disconnect from the timer signal which triggers at the given fixed time of day.
* If there are no remaining connections to that timer, it is destroyed.
*/
void DailyTimer::disconnect(const QTime& timeOfDay, QObject* receiver, const char* member)
{
	DailyTimer* timer = fixedInstance(timeOfDay, false);
	if (!timer)
		return;
	timer->disconnecT(receiver, member);
	if (!timer->hasConnections())
		delete timer;
}

/******************************************************************************
* Change the time at which the variable timer triggers.
*/
void DailyTimer::changeTime(const QTime& newTimeOfDay, bool triggerMissed)
{
	if (mFixed)
		return;
	if (mTimer->isActive())
	{
		mTimer->stop();
		bool triggerNow = false;
		if (triggerMissed)
		{
			QTime now = QTime::currentTime();
			if (now >= newTimeOfDay  &&  now < mTime)
			{
				// The trigger time is now earlier and it has already arrived today.
				// Trigger a timer event immediately.
				triggerNow = true;
			}
		}
		mTime = newTimeOfDay;
		if (triggerNow)
			mTimer->start(0);    // trigger immediately
		else
			start();
	}
	else
		mTime = newTimeOfDay;
}

/******************************************************************************
* Initialise the timer to trigger at the specified time.
* This will either be today or tomorrow, depending on whether the trigger time
* has already passed.
*/
void DailyTimer::start()
{
	// TIMEZONE = local time
	QDateTime now = QDateTime::currentDateTime();
	// Find out whether to trigger today or tomorrow.
	// In preference, use the last trigger date to determine this, since
	// that will avoid possible errors due to daylight savings time changes.
	bool today;
	if (mLastDate.isValid())
		today = (mLastDate < now.date());
	else
		today = (now.time() < mTime);
	QDateTime next;
	if (today)
		next = QDateTime(now.date(), mTime);
	else
		next = QDateTime(now.date().addDays(1), mTime);
	uint interval = next.toTime_t() - now.toTime_t();
	mTimer->start(interval * 1000);    // execute a single shot
	kDebug() << "at" << mTime.hour() << ":" << mTime.minute() << ": interval =" << interval/3600 << ":" << (interval/60)%60 << ":" << interval%60;
}

/******************************************************************************
* Called when the timer triggers.
* Set the timer to trigger again tomorrow at the specified time.
* Note that if daylight savings time changes occur, this will not be 24 hours
* from now.
*/
void DailyTimer::slotTimer()
{
	// TIMEZONE = local time
	QDateTime now = QDateTime::currentDateTime();
	mLastDate = now.date();
	QDateTime next = QDateTime(mLastDate.addDays(1), mTime);
	uint interval = next.toTime_t() - now.toTime_t();
	mTimer->start(interval * 1000);    // execute a single shot
	kDebug() << "at" << mTime.hour() << ":" << mTime.minute() << ": interval =" << interval/3600 << ":" << (interval/60)%60 << ":" << interval%60;
}
<|endoftext|>


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

Daemon GPL Source Code
Copyright (C) 2012 Unvanquished Developers

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Daemon Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Daemon Source Code is also subject to certain additional terms.
You should have received a copy of these additional terms immediately following the
terms and conditions of the GNU General Public License which accompanied the Daemon
Source Code.  If not, please request a copy in writing from id Software at the address
below.

If you have questions concerning this license or the applicable additional terms, you
may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
Maryland 20850 USA.

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

#include "rocketElement.h"
#include <Rocket/Core/Core.h>
#include <Rocket/Core/Factory.h>
#include <Rocket/Core/ElementInstancer.h>
#include <Rocket/Core/ElementInstancerGeneric.h>
#include "rocketConsoleTextElement.h"
extern "C"
{
#include "client.h"
}

extern Rocket::Core::Element *activeElement;

Rocket::Core::String Rocket_QuakeToRML( const char *in );

// File contains support code for custom rocket elements

void Rocket_GetElementTag( char *tag, int length )
{
	if ( activeElement )
	{
		Q_strncpyz( tag, activeElement->GetTagName().CString(), length );
	}
}

void Rocket_SetElementDimensions( float x, float y )
{
	if ( activeElement )
	{
		static_cast<RocketElement*>(activeElement)->SetDimensions( x, y );
	}
}

void Rocket_RegisterElement( const char *tag )
{
	Rocket::Core::Factory::RegisterElementInstancer( tag, new Rocket::Core::ElementInstancerGeneric< RocketElement >() )->RemoveReference();
}

// reduces an rml string to a common format so two rml strings can be compared
static Rocket::Core::String ReduceRML( const Rocket::Core::String &rml )
{
	Rocket::Core::String ret;
	Rocket::Core::String::size_type length = rml.Length();
	ret.Reserve( length );

	for ( int i = 0; i < length; i++ )
	{
		if ( rml[ i ] == ' ' || rml[ i ] == '\n' )
		{
			continue;
		}

		if ( rml[ i ] == '"' )
		{
			ret += '\'';
		}
		else
		{
			ret += rml[ i ];
		}
	}

	return ret;
}

static inline void Rocket_SetInnerRMLGuarded( Rocket::Core::Element *e, const Rocket::Core::String &newRML )
{
	Rocket::Core::String newReducedRML = ReduceRML( newRML );
	Rocket::Core::String oldReducedRML = ReduceRML( e->GetInnerRML() );

	if ( newReducedRML != oldReducedRML )
	{
		e->SetInnerRML( newRML );
	}
}

void Rocket_SetInnerRML( const char *name, const char *id, const char *RML, qboolean parseQuake )
{
	Rocket::Core::String newRML = parseQuake ? Rocket_QuakeToRML( RML ) : RML;

	if ( ( !*name || !*id ) && activeElement )
	{
		Rocket_SetInnerRMLGuarded( activeElement, newRML );
	}
	else
	{
		Rocket::Core::ElementDocument *document = menuContext->GetDocument( name );
		if ( document )
		{
			Rocket::Core::Element *e = document->GetElementById( id );

			if ( e )
			{
				Rocket_SetInnerRMLGuarded( e, newRML );
			}
		}
	}
}

void Rocket_GetAttribute( const char *name, const char *id, const char *attribute, char *out, int length )
{
	if ( ( !*name || !*id ) && activeElement )
	{
		Q_strncpyz( out, activeElement->GetAttribute< Rocket::Core::String >( attribute, "" ).CString(), length );
	}
	else
	{
		Rocket::Core::ElementDocument *document = menuContext->GetDocument( name );

		if ( document )
		{
			Q_strncpyz( out, document->GetElementById( id )->GetAttribute< Rocket::Core::String >( attribute, "" ).CString(), length );
		}
	}
}

void Rocket_SetAttribute( const char *name, const char *id, const char *attribute, const char *value )
{
	if ( ( !*name && !*id ) && activeElement )
	{
		activeElement->SetAttribute( attribute, value );
	}
	else
	{
		Rocket::Core::ElementDocument *document = name[0] ? menuContext->GetDocument( name ) : menuContext->GetFocusElement()->GetOwnerDocument();

		if ( document )
		{
			Rocket::Core::Element *element = document->GetElementById( id );

			if ( element )
			{
				element->SetAttribute( attribute, value );
			}
		}
	}
}

void Rocket_GetElementAbsoluteOffset( float *x, float *y )
{
	if ( activeElement )
	{
		Rocket::Core::Vector2f position = activeElement->GetAbsoluteOffset();
		*x = position.x;
		*y = position.y;
	}
	else
	{
		*x = -1;
		*y = -1;
	}
}

void Rocket_GetProperty( const char *name, void *out, int len, rocketVarType_t type )
{
	if ( activeElement )
	{
		const Rocket::Core::Property *property = activeElement->GetProperty( name );

		if ( !property )
		{
			return;
		}

		switch ( type )
		{
			case ROCKET_STRING:
			{
				char *string = ( char * ) out;
				if ( property )
				{
					Q_strncpyz( string, property->Get<Rocket::Core::String>().CString(), len );
				}
				return;
			}

			case ROCKET_FLOAT:
			{
				float *f = ( float * ) out;

				if ( len != sizeof( float ) )
				{
					return;
				}

				*f = property->Get<float>();
				return;
			}

			case ROCKET_INT:
			{
				int *i = ( int * ) out;

				if ( len != sizeof( int ) )
				{
					return;
				}

				*i = property->Get<int>();
				return;
			}

			case ROCKET_COLOR:
			{
				vec_t *outColor = ( vec_t * ) out;

				if ( len != sizeof( vec4_t ) )
				{
					return;
				}

				Rocket::Core::Colourb color = property->Get<Rocket::Core::Colourb>();
				outColor[ 0 ] = color.red, outColor[ 1 ] = color.green, outColor[ 2 ] = color.blue, outColor[ 3 ] = color.alpha;
				Vector4Scale( outColor, 1 / 255.0f, outColor );
				return;
			}
		}
	}
}

void Rocket_SetClass( const char *in, qboolean activate )
{
	activeElement->SetClass( in, static_cast<bool>( activate ) );
}

void Rocket_SetPropertyById( const char *id, const char *property, const char *value )
{
	if ( *id )
	{
		Rocket::Core::ElementDocument *document = menuContext->GetFocusElement()->GetOwnerDocument();

		if ( document )
		{
			Rocket::Core::Element *element = document->GetElementById( id );

			if ( element )
			{
				element->SetProperty( property, value );
			}
		}
	}
	else if ( activeElement )
	{
		activeElement->SetProperty( property, value );
	}
}
Rocket::Core::Container::deque<ConsoleLine>::Type RocketConsoleTextElement::lines = Rocket::Core::Container::deque<ConsoleLine>::Type();
void Rocket_AddConsoleText( void )
{
	static char buffer[ MAX_STRING_CHARS ];

	Cmd_LiteralArgsBuffer( buffer, sizeof( buffer ) );
	RocketConsoleTextElement::lines.push_front( ConsoleLine( buffer ) );
}
<commit_msg>Add a special case hack to get the real width and height when specified in non-absolute units.<commit_after>	/*
===========================================================================

Daemon GPL Source Code
Copyright (C) 2012 Unvanquished Developers

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Daemon Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Daemon Source Code is also subject to certain additional terms.
You should have received a copy of these additional terms immediately following the
terms and conditions of the GNU General Public License which accompanied the Daemon
Source Code.  If not, please request a copy in writing from id Software at the address
below.

If you have questions concerning this license or the applicable additional terms, you
may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
Maryland 20850 USA.

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

#include "rocketElement.h"
#include <Rocket/Core/Core.h>
#include <Rocket/Core/Factory.h>
#include <Rocket/Core/ElementInstancer.h>
#include <Rocket/Core/ElementInstancerGeneric.h>
#include "rocketConsoleTextElement.h"
extern "C"
{
#include "client.h"
}

extern Rocket::Core::Element *activeElement;

Rocket::Core::String Rocket_QuakeToRML( const char *in );

// File contains support code for custom rocket elements

void Rocket_GetElementTag( char *tag, int length )
{
	if ( activeElement )
	{
		Q_strncpyz( tag, activeElement->GetTagName().CString(), length );
	}
}

void Rocket_SetElementDimensions( float x, float y )
{
	if ( activeElement )
	{
		static_cast<RocketElement*>(activeElement)->SetDimensions( x, y );
	}
}

void Rocket_RegisterElement( const char *tag )
{
	Rocket::Core::Factory::RegisterElementInstancer( tag, new Rocket::Core::ElementInstancerGeneric< RocketElement >() )->RemoveReference();
}

// reduces an rml string to a common format so two rml strings can be compared
static Rocket::Core::String ReduceRML( const Rocket::Core::String &rml )
{
	Rocket::Core::String ret;
	Rocket::Core::String::size_type length = rml.Length();
	ret.Reserve( length );

	for ( int i = 0; i < length; i++ )
	{
		if ( rml[ i ] == ' ' || rml[ i ] == '\n' )
		{
			continue;
		}

		if ( rml[ i ] == '"' )
		{
			ret += '\'';
		}
		else
		{
			ret += rml[ i ];
		}
	}

	return ret;
}

static inline void Rocket_SetInnerRMLGuarded( Rocket::Core::Element *e, const Rocket::Core::String &newRML )
{
	Rocket::Core::String newReducedRML = ReduceRML( newRML );
	Rocket::Core::String oldReducedRML = ReduceRML( e->GetInnerRML() );

	if ( newReducedRML != oldReducedRML )
	{
		e->SetInnerRML( newRML );
	}
}

void Rocket_SetInnerRML( const char *name, const char *id, const char *RML, qboolean parseQuake )
{
	Rocket::Core::String newRML = parseQuake ? Rocket_QuakeToRML( RML ) : RML;

	if ( ( !*name || !*id ) && activeElement )
	{
		Rocket_SetInnerRMLGuarded( activeElement, newRML );
	}
	else
	{
		Rocket::Core::ElementDocument *document = menuContext->GetDocument( name );
		if ( document )
		{
			Rocket::Core::Element *e = document->GetElementById( id );

			if ( e )
			{
				Rocket_SetInnerRMLGuarded( e, newRML );
			}
		}
	}
}

void Rocket_GetAttribute( const char *name, const char *id, const char *attribute, char *out, int length )
{
	if ( ( !*name || !*id ) && activeElement )
	{
		Q_strncpyz( out, activeElement->GetAttribute< Rocket::Core::String >( attribute, "" ).CString(), length );
	}
	else
	{
		Rocket::Core::ElementDocument *document = menuContext->GetDocument( name );

		if ( document )
		{
			Q_strncpyz( out, document->GetElementById( id )->GetAttribute< Rocket::Core::String >( attribute, "" ).CString(), length );
		}
	}
}

void Rocket_SetAttribute( const char *name, const char *id, const char *attribute, const char *value )
{
	if ( ( !*name && !*id ) && activeElement )
	{
		activeElement->SetAttribute( attribute, value );
	}
	else
	{
		Rocket::Core::ElementDocument *document = name[0] ? menuContext->GetDocument( name ) : menuContext->GetFocusElement()->GetOwnerDocument();

		if ( document )
		{
			Rocket::Core::Element *element = document->GetElementById( id );

			if ( element )
			{
				element->SetAttribute( attribute, value );
			}
		}
	}
}

void Rocket_GetElementAbsoluteOffset( float *x, float *y )
{
	if ( activeElement )
	{
		Rocket::Core::Vector2f position = activeElement->GetAbsoluteOffset();
		*x = position.x;
		*y = position.y;
	}
	else
	{
		*x = -1;
		*y = -1;
	}
}

void Rocket_GetProperty( const char *name, void *out, int len, rocketVarType_t type )
{
	if ( activeElement )
	{
		const Rocket::Core::Property *property = activeElement->GetProperty( name );

		if ( !property )
		{
			return;
		}

		switch ( type )
		{
			case ROCKET_STRING:
			{
				char *string = ( char * ) out;
				if ( property )
				{
					Q_strncpyz( string, property->Get<Rocket::Core::String>().CString(), len );
				}
				return;
			}

			case ROCKET_FLOAT:
			{
				float *f = ( float * ) out;

				if ( len != sizeof( float ) )
				{
					return;
				}

				// HACK: special case for width and height specified in non absolute units

				if ( !Q_stricmp( "width", name ) && property->unit & Rocket::Core::Property::ABSOLUTE_UNIT )
				{
					float base_size = 0;
					Rocket::Core::Element *parent = activeElement;

					while ( parent = parent->GetParentNode() )
					{
						if ( ( base_size = parent->GetOffsetWidth() ) != 0 )
						{
							*f = activeElement->ResolveProperty( "width", base_size );
							return;
						}
					}
				}

				if ( !Q_stricmp( "height", name ) && property->unit & Rocket::Core::Property::ABSOLUTE_UNIT )
				{
					float base_size = 0;
					Rocket::Core::Element *parent = activeElement;

					while ( parent = parent->GetParentNode() )
					{
						if ( ( base_size = parent->GetOffsetHeight() ) != 0 )
						{
							*f = activeElement->ResolveProperty( "height", base_size );
							return;
						}
					}
				}

				*f = property->Get<float>();
				return;
			}

			case ROCKET_INT:
			{
				int *i = ( int * ) out;

				if ( len != sizeof( int ) )
				{
					return;
				}

				*i = property->Get<int>();
				return;
			}

			case ROCKET_COLOR:
			{
				vec_t *outColor = ( vec_t * ) out;

				if ( len != sizeof( vec4_t ) )
				{
					return;
				}

				Rocket::Core::Colourb color = property->Get<Rocket::Core::Colourb>();
				outColor[ 0 ] = color.red, outColor[ 1 ] = color.green, outColor[ 2 ] = color.blue, outColor[ 3 ] = color.alpha;
				Vector4Scale( outColor, 1 / 255.0f, outColor );
				return;
			}
		}
	}
}

void Rocket_SetClass( const char *in, qboolean activate )
{
	activeElement->SetClass( in, static_cast<bool>( activate ) );
}

void Rocket_SetPropertyById( const char *id, const char *property, const char *value )
{
	if ( *id )
	{
		Rocket::Core::ElementDocument *document = menuContext->GetFocusElement()->GetOwnerDocument();

		if ( document )
		{
			Rocket::Core::Element *element = document->GetElementById( id );

			if ( element )
			{
				element->SetProperty( property, value );
			}
		}
	}
	else if ( activeElement )
	{
		activeElement->SetProperty( property, value );
	}
}
Rocket::Core::Container::deque<ConsoleLine>::Type RocketConsoleTextElement::lines = Rocket::Core::Container::deque<ConsoleLine>::Type();
void Rocket_AddConsoleText( void )
{
	static char buffer[ MAX_STRING_CHARS ];

	Cmd_LiteralArgsBuffer( buffer, sizeof( buffer ) );
	RocketConsoleTextElement::lines.push_front( ConsoleLine( buffer ) );
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016 zScale Technology GmbH <legal@zscale.io>
 * Authors:
 *   - Paul Asmuth <paul@zscale.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include "eventql/eventql.h"
#include "eventql/util/logging.h"
#include <eventql/db/CompactionStrategy.h>
#include <eventql/db/LSMTableIndex.h>
#include <eventql/io/cstable/cstable_writer.h>
#include <eventql/util/io/fileutil.h>

namespace eventql {

SimpleCompactionStrategy::SimpleCompactionStrategy(
    RefPtr<Partition> partition,
    LSMTableIndexCache* idx_cache,
    size_t num_tables_soft_limit,
    size_t num_tables_hard_limit) :
    partition_(partition),
    idx_cache_(idx_cache),
    num_tables_soft_limit_(num_tables_soft_limit),
    num_tables_hard_limit_(num_tables_hard_limit) {}

bool SimpleCompactionStrategy::compact(
    const Vector<LSMTableRef>& input,
    Vector<LSMTableRef>* output) {
  if (input.empty()) {
    return false;
  }

  if (!needsCompaction(input)) {
    return false;
  }

  HashMap<SHA1Hash, uint64_t> vmap;
  for (auto tbl = input.rbegin(); tbl != input.rend(); ++tbl) {
    auto idx = idx_cache_->lookup(
        FileUtil::joinPaths(partition_->getRelativePath(), tbl->filename()));
    idx->list(&vmap);
  }

  auto table = partition_->getTable();
  auto base_path = partition_->getAbsolutePath();
  auto cstable_schema = cstable::TableSchema::fromProtobuf(*table->schema());
  auto cstable_schema_ext = cstable_schema;
  cstable_schema_ext.addBool("__lsm_is_update", false);
  cstable_schema_ext.addString("__lsm_id", false);
  cstable_schema_ext.addUnsignedInteger("__lsm_version", false);
  cstable_schema_ext.addUnsignedInteger("__lsm_sequence", false);

  auto cstable_filename = Random::singleton()->hex64();
  auto cstable_filepath = FileUtil::joinPaths(base_path, cstable_filename);

  auto cstable = cstable::CSTableWriter::createFile(
      cstable_filepath + ".cst",
      cstable::BinaryFormatVersion::v0_1_0,
      cstable_schema_ext);

  auto is_update_col = cstable->getColumnWriter("__lsm_is_update");
  auto id_col = cstable->getColumnWriter("__lsm_id");
  auto version_col = cstable->getColumnWriter("__lsm_version");
  auto sequence_col = cstable->getColumnWriter("__lsm_sequence");

  for (const auto& tbl : input) {
    auto input_cstable_file = FileUtil::joinPaths(
        base_path,
        tbl.filename() + ".cst");

    if (!FileUtil::exists(input_cstable_file)) {
      logWarning("evqld", "missing table file: $0", input_cstable_file);
      continue;
    }

    try {
      auto input_cstable = cstable::CSTableReader::openFile(input_cstable_file);
      auto input_id_col = input_cstable->getColumnReader("__lsm_id");
      auto input_version_col = input_cstable->getColumnReader("__lsm_version");
      auto input_sequence_col = input_cstable->getColumnReader("__lsm_sequence");

      Vector<Pair<
          RefPtr<cstable::ColumnReader>,
          RefPtr<cstable::ColumnWriter>>> columns;

      auto flat_columns = cstable_schema.flatColumns();
      for (const auto& col : flat_columns) {
        if (input_cstable->hasColumn(col.column_name)) {
          columns.emplace_back(
              input_cstable->getColumnReader(col.column_name),
              cstable->getColumnWriter(col.column_name));
        } else {
          if (col.dlevel_max == 0) {
            RAISE(
                kIllegalStateError,
                "can't merge CSTables after a new required column was added");
          }

          columns.emplace_back(
              nullptr,
              cstable->getColumnWriter(col.column_name));
        }
      }

      auto nrecords = input_cstable->numRecords();
      for (size_t i = 0; i < nrecords; ++i) {
        uint64_t rlvl;
        uint64_t dlvl;

        String id_str;
        input_id_col->readString(&rlvl, &dlvl, &id_str);
        SHA1Hash id(id_str.data(), id_str.size());

        uint64_t version;
        input_version_col->readUnsignedInt(&rlvl, &dlvl, &version);

        uint64_t sequence;
        input_sequence_col->readUnsignedInt(&rlvl, &dlvl, &sequence);

        const auto& vmap_iter = vmap.find(id);
        if (vmap_iter == vmap.end()) {
          RAISE(kIllegalStateError, "invalid cstable contents");
        }

        if (version == vmap_iter->second) {
          is_update_col->writeBoolean(0, 0, false);
          id_col->writeString(0, 0, id_str);
          version_col->writeUnsignedInt(0, 0, version);
          sequence_col->writeUnsignedInt(0, 0, sequence);

          for (auto& col : columns) {
            if (col.first.get()) {
              do {
                col.first->copyValue(col.second.get());
              } while (col.first->nextRepetitionLevel() > 0);
            } else {
              col.second->writeNull(0, 0);
            }
          }

          cstable->addRow();
        } else {
          for (auto& col : columns) {
            if (col.first.get()) {
              do {
                col.first->skipValue();
              } while (col.first->nextRepetitionLevel() > 0);
            }
          }
        }
      }
    } catch (const std::exception& e) {
      logError("evqld", "error while compacting table: $0", input_cstable_file);
    }
  }

  cstable->commit();

  OrderedMap<SHA1Hash, uint64_t> vmap_ordered;
  for (const auto& p : vmap) {
    vmap_ordered.emplace(p);
  }
  LSMTableIndex::write(vmap_ordered, cstable_filepath + ".idx");

  LSMTableRef tbl_ref;
  tbl_ref.set_filename(cstable_filename);
  tbl_ref.set_first_sequence(input.begin()->first_sequence());
  tbl_ref.set_last_sequence(input.rbegin()->last_sequence());
  tbl_ref.set_size_bytes(FileUtil::size(cstable_filepath + ".cst"));
  output->emplace_back(tbl_ref);

  return true;
}

bool SimpleCompactionStrategy::needsCompaction(
    const Vector<LSMTableRef>& tables) {
  return tables.size() > num_tables_soft_limit_;
}

bool SimpleCompactionStrategy::needsUrgentCompaction(
    const Vector<LSMTableRef>& tables) {
  return tables.size() > num_tables_hard_limit_;
}

} // namespace eventql

<commit_msg>more debug info<commit_after>/**
 * Copyright (c) 2016 zScale Technology GmbH <legal@zscale.io>
 * Authors:
 *   - Paul Asmuth <paul@zscale.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include "eventql/eventql.h"
#include "eventql/util/logging.h"
#include <eventql/db/CompactionStrategy.h>
#include <eventql/db/LSMTableIndex.h>
#include <eventql/io/cstable/cstable_writer.h>
#include <eventql/util/io/fileutil.h>

namespace eventql {

SimpleCompactionStrategy::SimpleCompactionStrategy(
    RefPtr<Partition> partition,
    LSMTableIndexCache* idx_cache,
    size_t num_tables_soft_limit,
    size_t num_tables_hard_limit) :
    partition_(partition),
    idx_cache_(idx_cache),
    num_tables_soft_limit_(num_tables_soft_limit),
    num_tables_hard_limit_(num_tables_hard_limit) {}

bool SimpleCompactionStrategy::compact(
    const Vector<LSMTableRef>& input,
    Vector<LSMTableRef>* output) {
  if (input.empty()) {
    return false;
  }

  if (!needsCompaction(input)) {
    return false;
  }

  HashMap<SHA1Hash, uint64_t> vmap;
  for (auto tbl = input.rbegin(); tbl != input.rend(); ++tbl) {
    auto idx = idx_cache_->lookup(
        FileUtil::joinPaths(partition_->getRelativePath(), tbl->filename()));
    idx->list(&vmap);
  }

  auto table = partition_->getTable();
  auto base_path = partition_->getAbsolutePath();
  auto cstable_schema = cstable::TableSchema::fromProtobuf(*table->schema());
  auto cstable_schema_ext = cstable_schema;
  cstable_schema_ext.addBool("__lsm_is_update", false);
  cstable_schema_ext.addString("__lsm_id", false);
  cstable_schema_ext.addUnsignedInteger("__lsm_version", false);
  cstable_schema_ext.addUnsignedInteger("__lsm_sequence", false);

  auto cstable_filename = Random::singleton()->hex64();
  auto cstable_filepath = FileUtil::joinPaths(base_path, cstable_filename);

  auto cstable = cstable::CSTableWriter::createFile(
      cstable_filepath + ".cst",
      cstable::BinaryFormatVersion::v0_1_0,
      cstable_schema_ext);

  auto is_update_col = cstable->getColumnWriter("__lsm_is_update");
  auto id_col = cstable->getColumnWriter("__lsm_id");
  auto version_col = cstable->getColumnWriter("__lsm_version");
  auto sequence_col = cstable->getColumnWriter("__lsm_sequence");

  for (const auto& tbl : input) {
    auto input_cstable_file = FileUtil::joinPaths(
        base_path,
        tbl.filename() + ".cst");

    if (!FileUtil::exists(input_cstable_file)) {
      logWarning("evqld", "missing table file: $0", input_cstable_file);
      continue;
    }

    try {
      auto input_cstable = cstable::CSTableReader::openFile(input_cstable_file);
      auto input_id_col = input_cstable->getColumnReader("__lsm_id");
      auto input_version_col = input_cstable->getColumnReader("__lsm_version");
      auto input_sequence_col = input_cstable->getColumnReader("__lsm_sequence");

      Vector<Pair<
          RefPtr<cstable::ColumnReader>,
          RefPtr<cstable::ColumnWriter>>> columns;

      auto flat_columns = cstable_schema.flatColumns();
      for (const auto& col : flat_columns) {
        if (input_cstable->hasColumn(col.column_name)) {
          columns.emplace_back(
              input_cstable->getColumnReader(col.column_name),
              cstable->getColumnWriter(col.column_name));
        } else {
          if (col.dlevel_max == 0) {
            RAISE(
                kIllegalStateError,
                "can't merge CSTables after a new required column was added");
          }

          columns.emplace_back(
              nullptr,
              cstable->getColumnWriter(col.column_name));
        }
      }

      auto nrecords = input_cstable->numRecords();
      for (size_t i = 0; i < nrecords; ++i) {
        uint64_t rlvl;
        uint64_t dlvl;

        String id_str;
        input_id_col->readString(&rlvl, &dlvl, &id_str);
        SHA1Hash id(id_str.data(), id_str.size());

        uint64_t version;
        input_version_col->readUnsignedInt(&rlvl, &dlvl, &version);

        uint64_t sequence;
        input_sequence_col->readUnsignedInt(&rlvl, &dlvl, &sequence);

        const auto& vmap_iter = vmap.find(id);
        if (vmap_iter == vmap.end()) {
          RAISE(kIllegalStateError, "invalid cstable contents");
        }

        if (version == vmap_iter->second) {
          is_update_col->writeBoolean(0, 0, false);
          id_col->writeString(0, 0, id_str);
          version_col->writeUnsignedInt(0, 0, version);
          sequence_col->writeUnsignedInt(0, 0, sequence);

          for (auto& col : columns) {
            if (col.first.get()) {
              do {
                col.first->copyValue(col.second.get());
              } while (col.first->nextRepetitionLevel() > 0);
            } else {
              col.second->writeNull(0, 0);
            }
          }

          cstable->addRow();
        } else {
          for (auto& col : columns) {
            if (col.first.get()) {
              do {
                col.first->skipValue();
              } while (col.first->nextRepetitionLevel() > 0);
            }
          }
        }
      }
    } catch (const std::exception& e) {
      logError(
          "evqld",
          "error while compacting table: $0 -- $1",
          input_cstable_file,
          e.what());
    }
  }

  cstable->commit();

  OrderedMap<SHA1Hash, uint64_t> vmap_ordered;
  for (const auto& p : vmap) {
    vmap_ordered.emplace(p);
  }
  LSMTableIndex::write(vmap_ordered, cstable_filepath + ".idx");

  LSMTableRef tbl_ref;
  tbl_ref.set_filename(cstable_filename);
  tbl_ref.set_first_sequence(input.begin()->first_sequence());
  tbl_ref.set_last_sequence(input.rbegin()->last_sequence());
  tbl_ref.set_size_bytes(FileUtil::size(cstable_filepath + ".cst"));
  output->emplace_back(tbl_ref);

  return true;
}

bool SimpleCompactionStrategy::needsCompaction(
    const Vector<LSMTableRef>& tables) {
  return tables.size() > num_tables_soft_limit_;
}

bool SimpleCompactionStrategy::needsUrgentCompaction(
    const Vector<LSMTableRef>& tables) {
  return tables.size() > num_tables_hard_limit_;
}

} // namespace eventql

<|endoftext|>


<commit_before>#include "./frame_buffer_object.h"
#include <QDebug>
#include <vector>
#include "./gl.h"

namespace Graphics
{

FrameBufferObject::FrameBufferObject(unsigned int layerCount)
  : layerCount(layerCount)
{
}

FrameBufferObject::~FrameBufferObject()
{
  glAssert(gl->glDeleteBuffers(1, &framebuffer));
  glAssert(gl->glDeleteBuffers(1, &depthTexture));
  glAssert(gl->glDeleteTextures(1, &colorTexturesArray));
  glAssert(gl->glDeleteTextures(1, &accumulatedLayersTexture));
}

void FrameBufferObject::initialize(Gl *gl, int width, int height)
{
  this->gl = gl;

  glAssert(gl->glGenFramebuffers(1, &framebuffer));
  glAssert(gl->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer));

  glAssert(gl->glGenTextures(1, &depthTexture));
  resizeAndSetDepthAttachment(width, height);

  glAssert(gl->glGenTextures(1, &colorTexturesArray));
  resizeAndSetColorArrayAttachment(colorTexturesArray, GL_COLOR_ATTACHMENT0,
                                   width, height);

  glAssert(gl->glGenTextures(1, &accumulatedLayersTexture));
  resizeAndSetColorAttachment(accumulatedLayersTexture,
                              GL_COLOR_ATTACHMENT0 + layerCount, width, height);

  glAssert(gl->glBindTexture(GL_TEXTURE_2D, 0));

  std::vector<GLenum> drawBuffers(layerCount + 1);
  for (unsigned int i = 0; i < layerCount + 1; ++i)
    drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
  glAssert(gl->glDrawBuffers(layerCount + 1, drawBuffers.data()));

  auto status = gl->glCheckFramebufferStatus(GL_FRAMEBUFFER);
  if (status != GL_FRAMEBUFFER_COMPLETE)
    throw std::runtime_error("Framebuffer not complete " +
                             std::to_string(status));

  unbind();
}

void FrameBufferObject::resize(int width, int height)
{
  bind();

  resizeAndSetDepthAttachment(width, height);

  gl->glDeleteTextures(1, &accumulatedLayersTexture);
  gl->glGenTextures(1, &accumulatedLayersTexture);
  resizeAndSetColorAttachment(accumulatedLayersTexture,
                              GL_COLOR_ATTACHMENT0 + layerCount, width, height);
  resizeAndSetColorArrayAttachment(colorTexturesArray, GL_COLOR_ATTACHMENT0,
                                   width, height);

  glAssert(gl->glBindTexture(GL_TEXTURE_2D, 0));

  unbind();
}

void FrameBufferObject::bind()
{
  glAssert(gl->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer));
}

void FrameBufferObject::unbind()
{
  glAssert(gl->glBindFramebuffer(GL_FRAMEBUFFER, 0));
}

void FrameBufferObject::bindColorTexture(unsigned int textureUnit)
{
  glAssert(gl->glActiveTexture(textureUnit));
  glAssert(gl->glBindTexture(GL_TEXTURE_3D, colorTexturesArray));
}

void FrameBufferObject::bindAccumulatedLayersTexture(unsigned int textureUnit)
{
  glAssert(gl->glActiveTexture(textureUnit));
  glAssert(gl->glBindTexture(GL_TEXTURE_2D, accumulatedLayersTexture));
}

void FrameBufferObject::bindDepthTexture(unsigned int textureUnit)
{
  glAssert(gl->glActiveTexture(textureUnit));
  glAssert(gl->glBindTexture(GL_TEXTURE_2D, depthTexture));
}

void FrameBufferObject::resizeAndSetColorAttachment(unsigned int texture,
                                                    int attachment, int width,
                                                    int height)
{
  resizeTexture(texture, width, height, GL_RGBA, GL_RGBA16F, GL_FLOAT);
  glAssert(gl->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment,
                                      GL_TEXTURE_2D, texture, 0));
}

void FrameBufferObject::resizeAndSetColorArrayAttachment(
    unsigned int texture, unsigned int attachment, int width, int height)
{
  gl->glBindTexture(GL_TEXTURE_3D, texture);
  gl->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  gl->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  gl->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA16F, width, height, layerCount, 0,
                   GL_RGBA, GL_FLOAT, nullptr);

  for (unsigned int layerIndex = 0; layerIndex < layerCount; ++layerIndex)
    glAssert(gl->glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER,
                                        attachment + layerIndex, GL_TEXTURE_3D,
                                        texture, 0, layerIndex));

  gl->glBindTexture(GL_TEXTURE_3D, 0);
}

void FrameBufferObject::resizeAndSetDepthAttachment(int width, int height)
{
  resizeTexture(depthTexture, width, height, GL_DEPTH_STENCIL,
                GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8);
  glAssert(gl->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
                                      GL_DEPTH_STENCIL_ATTACHMENT,
                                      GL_TEXTURE_2D, depthTexture, 0));
}

void FrameBufferObject::resizeTexture(unsigned int texture, int width,
                                      int height, unsigned int component,
                                      unsigned int format, unsigned int type)
{
  gl->glBindTexture(GL_TEXTURE_2D, texture);
  gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  gl->glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, component, type,
                   nullptr);
}

unsigned int FrameBufferObject::getColorTextureId()
{
  return colorTexturesArray;
}

unsigned int FrameBufferObject::getAccumulatedLayersTextureId()
{
  return accumulatedLayersTexture;
}

unsigned int FrameBufferObject::getDepthTextureId()
{
  return depthTexture;
}

int FrameBufferObject::getLayerCount()
{
  return layerCount;
}

}  // namespace Graphics

<commit_msg>Document bug workaround.<commit_after>#include "./frame_buffer_object.h"
#include <QDebug>
#include <vector>
#include "./gl.h"

namespace Graphics
{

FrameBufferObject::FrameBufferObject(unsigned int layerCount)
  : layerCount(layerCount)
{
}

FrameBufferObject::~FrameBufferObject()
{
  glAssert(gl->glDeleteBuffers(1, &framebuffer));
  glAssert(gl->glDeleteBuffers(1, &depthTexture));
  glAssert(gl->glDeleteTextures(1, &colorTexturesArray));
  glAssert(gl->glDeleteTextures(1, &accumulatedLayersTexture));
}

void FrameBufferObject::initialize(Gl *gl, int width, int height)
{
  this->gl = gl;

  glAssert(gl->glGenFramebuffers(1, &framebuffer));
  glAssert(gl->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer));

  glAssert(gl->glGenTextures(1, &depthTexture));
  resizeAndSetDepthAttachment(width, height);

  glAssert(gl->glGenTextures(1, &colorTexturesArray));
  resizeAndSetColorArrayAttachment(colorTexturesArray, GL_COLOR_ATTACHMENT0,
                                   width, height);

  glAssert(gl->glGenTextures(1, &accumulatedLayersTexture));
  resizeAndSetColorAttachment(accumulatedLayersTexture,
                              GL_COLOR_ATTACHMENT0 + layerCount, width, height);

  glAssert(gl->glBindTexture(GL_TEXTURE_2D, 0));

  std::vector<GLenum> drawBuffers(layerCount + 1);
  for (unsigned int i = 0; i < layerCount + 1; ++i)
    drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
  glAssert(gl->glDrawBuffers(layerCount + 1, drawBuffers.data()));

  auto status = gl->glCheckFramebufferStatus(GL_FRAMEBUFFER);
  if (status != GL_FRAMEBUFFER_COMPLETE)
    throw std::runtime_error("Framebuffer not complete " +
                             std::to_string(status));

  unbind();
}

void FrameBufferObject::resize(int width, int height)
{
  bind();

  resizeAndSetDepthAttachment(width, height);

  // TODO(all): investigate why deleting and generating a new texture is
  // necessary. If this is not done, an GL_INVALID_OPERATION causes the
  // application to crash.
  // Before switching to a 3D texture for the colors, this was not necessary.
  gl->glDeleteTextures(1, &accumulatedLayersTexture);
  gl->glGenTextures(1, &accumulatedLayersTexture);
  resizeAndSetColorAttachment(accumulatedLayersTexture,
                              GL_COLOR_ATTACHMENT0 + layerCount, width, height);
  resizeAndSetColorArrayAttachment(colorTexturesArray, GL_COLOR_ATTACHMENT0,
                                   width, height);

  glAssert(gl->glBindTexture(GL_TEXTURE_2D, 0));

  unbind();
}

void FrameBufferObject::bind()
{
  glAssert(gl->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer));
}

void FrameBufferObject::unbind()
{
  glAssert(gl->glBindFramebuffer(GL_FRAMEBUFFER, 0));
}

void FrameBufferObject::bindColorTexture(unsigned int textureUnit)
{
  glAssert(gl->glActiveTexture(textureUnit));
  glAssert(gl->glBindTexture(GL_TEXTURE_3D, colorTexturesArray));
}

void FrameBufferObject::bindAccumulatedLayersTexture(unsigned int textureUnit)
{
  glAssert(gl->glActiveTexture(textureUnit));
  glAssert(gl->glBindTexture(GL_TEXTURE_2D, accumulatedLayersTexture));
}

void FrameBufferObject::bindDepthTexture(unsigned int textureUnit)
{
  glAssert(gl->glActiveTexture(textureUnit));
  glAssert(gl->glBindTexture(GL_TEXTURE_2D, depthTexture));
}

void FrameBufferObject::resizeAndSetColorAttachment(unsigned int texture,
                                                    int attachment, int width,
                                                    int height)
{
  resizeTexture(texture, width, height, GL_RGBA, GL_RGBA16F, GL_FLOAT);
  glAssert(gl->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment,
                                      GL_TEXTURE_2D, texture, 0));
}

void FrameBufferObject::resizeAndSetColorArrayAttachment(
    unsigned int texture, unsigned int attachment, int width, int height)
{
  gl->glBindTexture(GL_TEXTURE_3D, texture);
  gl->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  gl->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  gl->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA16F, width, height, layerCount, 0,
                   GL_RGBA, GL_FLOAT, nullptr);

  for (unsigned int layerIndex = 0; layerIndex < layerCount; ++layerIndex)
    glAssert(gl->glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER,
                                        attachment + layerIndex, GL_TEXTURE_3D,
                                        texture, 0, layerIndex));

  gl->glBindTexture(GL_TEXTURE_3D, 0);
}

void FrameBufferObject::resizeAndSetDepthAttachment(int width, int height)
{
  resizeTexture(depthTexture, width, height, GL_DEPTH_STENCIL,
                GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8);
  glAssert(gl->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
                                      GL_DEPTH_STENCIL_ATTACHMENT,
                                      GL_TEXTURE_2D, depthTexture, 0));
}

void FrameBufferObject::resizeTexture(unsigned int texture, int width,
                                      int height, unsigned int component,
                                      unsigned int format, unsigned int type)
{
  gl->glBindTexture(GL_TEXTURE_2D, texture);
  gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  gl->glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, component, type,
                   nullptr);
}

unsigned int FrameBufferObject::getColorTextureId()
{
  return colorTexturesArray;
}

unsigned int FrameBufferObject::getAccumulatedLayersTextureId()
{
  return accumulatedLayersTexture;
}

unsigned int FrameBufferObject::getDepthTextureId()
{
  return depthTexture;
}

int FrameBufferObject::getLayerCount()
{
  return layerCount;
}

}  // namespace Graphics

<|endoftext|>


<commit_before><commit_msg>grt: add comment for resizing check<commit_after><|endoftext|>


<commit_before>/**
 * \file
 * \brief SoftwareTimer class implementation
 *
 * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-11-14
 */

#include "distortos/SoftwareTimer.hpp"

namespace distortos
{

/*---------------------------------------------------------------------------------------------------------------------+
| private static functions
+---------------------------------------------------------------------------------------------------------------------*/

void SoftwareTimer::softwareTimerRunner(SoftwareTimer& softwareTimer)
{
	softwareTimer.execute();
}

}	// namespace distortos
<commit_msg>SoftwareTimer::softwareTimerRunner(): call run() instead of execute()<commit_after>/**
 * \file
 * \brief SoftwareTimer class implementation
 *
 * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-11-15
 */

#include "distortos/SoftwareTimer.hpp"

namespace distortos
{

/*---------------------------------------------------------------------------------------------------------------------+
| private static functions
+---------------------------------------------------------------------------------------------------------------------*/

void SoftwareTimer::softwareTimerRunner(SoftwareTimer& softwareTimer)
{
	softwareTimer.run();
}

}	// namespace distortos
<|endoftext|>