<commit_before>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Kaveh Vahedipour
////////////////////////////////////////////////////////////////////////////////

#include "Agent.h"
#include "Basics/ConditionLocker.h"
#include "VocBase/server.h"
#include "VocBase/vocbase.h"

#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>

#include <chrono>
#include <iostream>

using namespace arangodb::velocypack;

namespace arangodb {
namespace consensus {

//  Agent configuration
Agent::Agent (TRI_server_t* server, config_t const& config, ApplicationV8* applicationV8, aql::QueryRegistry* queryRegistry)
    : Thread ("Agent"),
      _server(server),
      _vocbase(nullptr),
      _applicationV8(applicationV8),
      _queryRegistry(queryRegistry),
      _config(config),
      _last_commit_index(0) {

  _state.setEndPoint(_config.end_point);
  _constituent.configure(this);
  _confirmed.resize(size(),0); // agency's size and reset to 0
}

//  This agent's id
id_t Agent::id() const {
  return _config.id;
}

//  Shutdown
Agent::~Agent () {
  if (_vocbase != nullptr) {
    TRI_ReleaseDatabaseServer(_server, _vocbase);
  }
  shutdown();
}

//  State machine
State const& Agent::state () const {
  return _state;
}

//  Start all agent thread
bool Agent::start() {
  LOG_TOPIC(INFO, Logger::AGENCY) << "Starting agency comm worker.";
  Thread::start();
  return true;
}

//  This agent's term
term_t Agent::term () const {
  return _constituent.term();
}

//  Agency size
inline size_t Agent::size() const {
  return _config.size();
}

//  Handle vote request
priv_rpc_ret_t Agent::requestVote(term_t t, id_t id, index_t lastLogIndex,
                                  index_t lastLogTerm, query_t const& query) {

  /// Are we receiving new endpoints
  if (query != nullptr) { // record new endpoints
    if (query->slice().hasKey("endpoints") &&
        query->slice().get("endpoints").isArray()) {
      size_t j = 0;
      for (auto const& i : VPackArrayIterator(query->slice().get("endpoints"))) {
        _config.end_points[j++] = i.copyString();
      }
    }
  }

  /// Constituent handles this
  return priv_rpc_ret_t(
    _constituent.vote(t, id, lastLogIndex, lastLogTerm), this->term());

}

//  Get configuration
config_t const& Agent::config () const {
  return _config;
}

//  Leader's id
id_t Agent::leaderID () const {
  return _constituent.leaderID();
}

// Are we leading?
bool Agent::leading() const {
  return _constituent.leading();
}

// Persist term and id we vote for
void Agent::persist(term_t t, id_t i) {
//  _state.persist(t, i);
}

// Waits here for confirmation of log's commits up to index.
// Timeout in seconds
bool Agent::waitFor (index_t index, double timeout) {

  if (size() == 1) // single host agency
    return true;

  CONDITION_LOCKER(guard, _rest_cv);

  // Wait until woken up through AgentCallback
  while (true) {

    std::cout << _last_commit_index << std::endl;
    /// success?
    if (_last_commit_index >= index) {
      return true;
    }
    // timeout
    if (_rest_cv.wait(static_cast<uint64_t>(1.0e6*timeout))) {
      return false;
    }

    // shutting down
    if (this->isStopping()) {
      return false;
    }

  }
  // We should never get here
  TRI_ASSERT(false);
}

//  AgentCallback reports id of follower and its highest processed index
void Agent::reportIn (id_t id, index_t index) {
  MUTEX_LOCKER(mutexLocker, _ioLock);

  if (index > _confirmed[id])      // progress this follower?
    _confirmed[id] = index;

  if(index > _last_commit_index) { // progress last commit?
    size_t n = 0;
    for (size_t i = 0; i < size(); ++i) {
      n += (_confirmed[i]>=index);
    }
    if (n>size()/2) { // catch up read database and commit index
      LOG_TOPIC(INFO, Logger::AGENCY) << "Critical mass for commiting " <<
        _last_commit_index+1 << " through " << index << " to read db";

      _read_db.apply(_state.slices(_last_commit_index+1, index));
      _last_commit_index = index;
    }
  }

  CONDITION_LOCKER(guard, _rest_cv);
  _rest_cv.broadcast();            // wake up REST handlers
}

//  Followers' append entries
bool Agent::recvAppendEntriesRPC (term_t term, id_t leaderId, index_t prevIndex,
  term_t prevTerm, index_t leaderCommitIndex, query_t const& queries) {
  //Update commit index

  if (queries->slice().type() != VPackValueType::Array) {
    LOG_TOPIC(WARN, Logger::AGENCY)
      << "Received malformed entries for appending. Discarting!";
    return false;
  }

  MUTEX_LOCKER(mutexLocker, _ioLock);

  index_t last_commit_index = _last_commit_index;
  // 1. Reply false if term < currentTerm (§5.1)
  if (this->term() > term) {
    LOG_TOPIC(WARN, Logger::AGENCY) << "I have a higher term than RPC caller.";
    return false;
  }

  // 2. Reply false if log doesn’t contain an entry at prevLogIndex
  //    whose term matches prevLogTerm (§5.3)
  if (!_state.find(prevIndex,prevTerm)) {
    LOG_TOPIC(WARN, Logger::AGENCY)
      << "Unable to find matching entry to previous entry (index,term) = ("
      << prevIndex << "," << prevTerm << ")";
    //return false;
  }

  // 3. If an existing entry conflicts with a new one (same index
  //    but different terms), delete the existing entry and all that
  //    follow it (§5.3)
  // 4. Append any new entries not already in the log
  if (queries->slice().length()) {
    LOG_TOPIC(INFO, Logger::AGENCY) << "Appending "<< queries->slice().length()
                                    << " entries to state machine.";
    /* bool success = */_state.log (queries, term, leaderId, prevIndex, prevTerm);
  } else {
    // heart-beat
  }

  // appendEntries 5. If leaderCommit > commitIndex, set commitIndex =
  //min(leaderCommit, index of last new entry)
  if (leaderCommitIndex > last_commit_index) {
    _last_commit_index = (std::min)(leaderCommitIndex,last_commit_index);
  }

  return true;

}

// Leader's append entries
append_entries_t Agent::sendAppendEntriesRPC (id_t follower_id) {

  index_t last_confirmed = _confirmed[follower_id];
  std::vector<log_t> unconfirmed = _state.get(last_confirmed);

  MUTEX_LOCKER(mutexLocker, _ioLock);

  term_t t = this->term();

  // RPC path
  std::stringstream path;
  path << "/_api/agency_priv/appendEntries?term=" << t << "&leaderId="
       << id() << "&prevLogIndex=" << unconfirmed[0].index << "&prevLogTerm="
       << unconfirmed[0].term << "&leaderCommit=" << _last_commit_index;

  // Headers
	std::unique_ptr<std::map<std::string, std::string>> headerFields =
	  std::make_unique<std::map<std::string, std::string> >();

  // Body
  Builder builder;
  index_t last = unconfirmed[0].index;
  builder.add(VPackValue(VPackValueType::Array));
  for (size_t i = 1; i < unconfirmed.size(); ++i) {
    builder.add (VPackValue(VPackValueType::Object));
    builder.add ("index", VPackValue(unconfirmed[i].index));
    builder.add ("query", VPackSlice(unconfirmed[i].entry->data()));
    builder.close();
    last = unconfirmed[i].index;
  }
  builder.close();

  // Send request
  if (unconfirmed.size() > 1) {
    LOG_TOPIC(INFO, Logger::AGENCY)
      << "Appending " << unconfirmed.size()-1 << " entries up to index " << last
      << " to follower " << follower_id;
  }

  arangodb::ClusterComm::instance()->asyncRequest
    ("1", 1, _config.end_points[follower_id],
     arangodb::GeneralRequest::RequestType::POST,
     path.str(), std::make_shared<std::string>(builder.toJson()), headerFields,
     std::make_shared<AgentCallback>(this, follower_id, last),
     0, true);

  return append_entries_t(t, true);

}

// @brief load persistent state
bool Agent::load () {
  TRI_vocbase_t* vocbase =
      TRI_UseDatabaseServer(_server, TRI_VOC_SYSTEM_DATABASE);

  if (vocbase == nullptr) {
    LOG(FATAL) << "could not determine _system database";
    FATAL_ERROR_EXIT();
  }

  _vocbase = vocbase;

  LOG_TOPIC(INFO, Logger::AGENCY) << "Loading persistent state.";
  if (!_state.loadCollections(_vocbase, _applicationV8, _queryRegistry)) {
    LOG_TOPIC(WARN, Logger::AGENCY) << "Failed to load persistent state on statup.";
  }

  LOG_TOPIC(INFO, Logger::AGENCY) << "Reassembling spearhead and read stores.";
//  _read_db.apply(_state.slices());
  _spearhead.apply(_state.slices(_last_commit_index+1));

  LOG_TOPIC(INFO, Logger::AGENCY) << "Starting spearhead worker.";
  _spearhead.start(this);
  _read_db.start(this);

  LOG_TOPIC(INFO, Logger::AGENCY) << "Starting constituent personality.";
  _constituent.start(_vocbase, _applicationV8, _queryRegistry);

  return true;
}

// Write new entries to replicated state and store
write_ret_t Agent::write (query_t const& query)  {

  if (_constituent.leading()) {                    // Only working as leader

    std::vector<bool> applied;
    std::vector<index_t> indices;
    index_t maxind = 0;

    {
      MUTEX_LOCKER(mutexLocker, _ioLock);
      applied = _spearhead.apply(query);             // Apply to spearhead
      indices = _state.log (query, applied, term(), id()); // Log w/ indicies
      if (!indices.empty()) {
        maxind = *std::max_element(indices.begin(), indices.end());
      }
      _cv.signal();                                  // Wake up run
    }

    reportIn(0,maxind);

    return write_ret_t(true,id(),applied,indices); // Indices to wait for to rest

  } else {                                         // Else we redirect
    return write_ret_t(false,_constituent.leaderID());
  }
}

// Read from store
read_ret_t Agent::read (query_t const& query) const {
  if (_constituent.leading()) {     // Only working as leaer
    query_t result = std::make_shared<arangodb::velocypack::Builder>();
    std::vector<bool> success = _read_db.read (query, result);
    return read_ret_t(true, _constituent.leaderID(), success, result);
  } else {                          // Else We redirect
    return read_ret_t(false, _constituent.leaderID());
  }
}

// Repeated append entries
void Agent::run() {

  CONDITION_LOCKER(guard, _cv);

  while (!this->isStopping()) {

    if (leading())
      _cv.wait(250000); // Only if leading
    else
      _cv.wait();       // Just sit there doing nothing

    // Collect all unacknowledged
    for (id_t i = 0; i < size(); ++i) {
      if (i != id()) {
        sendAppendEntriesRPC(i);
      }
    }
  }

}

// Orderly shutdown
void Agent::beginShutdown() {

  if (_vocbase != nullptr) {
    TRI_ReleaseDatabaseServer(_server, _vocbase);
  }

  // Personal hygiene
  Thread::beginShutdown();

  // Stop constituent and key value stores
  _constituent.beginShutdown();
  _spearhead.beginShutdown();
  _read_db.beginShutdown();

  // Wake up all waiting REST handler (waitFor)
  CONDITION_LOCKER(guard, _cv);
  guard.broadcast();

}

// Becoming leader
bool Agent::lead () {

  // Key value stores
  rebuildDBs();

  // Wake up run
  _cv.signal();

  return true;
}

// Rebuild key value stores
bool Agent::rebuildDBs() {
  MUTEX_LOCKER(mutexLocker, _ioLock);
  _spearhead.apply(_state.slices());
  _read_db.apply(_state.slices());
  return true;
}

// Last log entry
log_t const& Agent::lastLog() const {
  return _state.lastLog();
}

// Get spearhead
Store const& Agent::spearhead () const {
  return _spearhead;
}

// Get readdb
Store const& Agent::readDB () const {
  return _read_db;
}

}}
<commit_msg>TRI_ReleaseDatabaseServer moved to end of beginshutdown<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Kaveh Vahedipour
////////////////////////////////////////////////////////////////////////////////

#include "Agent.h"
#include "Basics/ConditionLocker.h"
#include "VocBase/server.h"
#include "VocBase/vocbase.h"

#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>

#include <chrono>
#include <iostream>

using namespace arangodb::velocypack;

namespace arangodb {
namespace consensus {

//  Agent configuration
Agent::Agent (TRI_server_t* server, config_t const& config, ApplicationV8* applicationV8, aql::QueryRegistry* queryRegistry)
    : Thread ("Agent"),
      _server(server),
      _vocbase(nullptr),
      _applicationV8(applicationV8),
      _queryRegistry(queryRegistry),
      _config(config),
      _last_commit_index(0) {

  _state.setEndPoint(_config.end_point);
  _constituent.configure(this);
  _confirmed.resize(size(),0); // agency's size and reset to 0
}

//  This agent's id
id_t Agent::id() const {
  return _config.id;
}

//  Shutdown
Agent::~Agent () {
  shutdown();
}

//  State machine
State const& Agent::state () const {
  return _state;
}

//  Start all agent thread
bool Agent::start() {
  LOG_TOPIC(INFO, Logger::AGENCY) << "Starting agency comm worker.";
  Thread::start();
  return true;
}

//  This agent's term
term_t Agent::term () const {
  return _constituent.term();
}

//  Agency size
inline size_t Agent::size() const {
  return _config.size();
}

//  Handle vote request
priv_rpc_ret_t Agent::requestVote(term_t t, id_t id, index_t lastLogIndex,
                                  index_t lastLogTerm, query_t const& query) {

  /// Are we receiving new endpoints
  if (query != nullptr) { // record new endpoints
    if (query->slice().hasKey("endpoints") &&
        query->slice().get("endpoints").isArray()) {
      size_t j = 0;
      for (auto const& i : VPackArrayIterator(query->slice().get("endpoints"))) {
        _config.end_points[j++] = i.copyString();
      }
    }
  }

  /// Constituent handles this
  return priv_rpc_ret_t(
    _constituent.vote(t, id, lastLogIndex, lastLogTerm), this->term());

}

//  Get configuration
config_t const& Agent::config () const {
  return _config;
}

//  Leader's id
id_t Agent::leaderID () const {
  return _constituent.leaderID();
}

// Are we leading?
bool Agent::leading() const {
  return _constituent.leading();
}

// Persist term and id we vote for
void Agent::persist(term_t t, id_t i) {
//  _state.persist(t, i);
}

// Waits here for confirmation of log's commits up to index.
// Timeout in seconds
bool Agent::waitFor (index_t index, double timeout) {

  if (size() == 1) // single host agency
    return true;

  CONDITION_LOCKER(guard, _rest_cv);

  // Wait until woken up through AgentCallback
  while (true) {

    std::cout << _last_commit_index << std::endl;
    /// success?
    if (_last_commit_index >= index) {
      return true;
    }
    // timeout
    if (_rest_cv.wait(static_cast<uint64_t>(1.0e6*timeout))) {
      return false;
    }

    // shutting down
    if (this->isStopping()) {
      return false;
    }

  }
  // We should never get here
  TRI_ASSERT(false);
}

//  AgentCallback reports id of follower and its highest processed index
void Agent::reportIn (id_t id, index_t index) {
  MUTEX_LOCKER(mutexLocker, _ioLock);

  if (index > _confirmed[id])      // progress this follower?
    _confirmed[id] = index;

  if(index > _last_commit_index) { // progress last commit?
    size_t n = 0;
    for (size_t i = 0; i < size(); ++i) {
      n += (_confirmed[i]>=index);
    }
    if (n>size()/2) { // catch up read database and commit index
      LOG_TOPIC(INFO, Logger::AGENCY) << "Critical mass for commiting " <<
        _last_commit_index+1 << " through " << index << " to read db";

      _read_db.apply(_state.slices(_last_commit_index+1, index));
      _last_commit_index = index;
    }
  }

  CONDITION_LOCKER(guard, _rest_cv);
  _rest_cv.broadcast();            // wake up REST handlers
}

//  Followers' append entries
bool Agent::recvAppendEntriesRPC (term_t term, id_t leaderId, index_t prevIndex,
  term_t prevTerm, index_t leaderCommitIndex, query_t const& queries) {
  //Update commit index

  if (queries->slice().type() != VPackValueType::Array) {
    LOG_TOPIC(WARN, Logger::AGENCY)
      << "Received malformed entries for appending. Discarting!";
    return false;
  }

  MUTEX_LOCKER(mutexLocker, _ioLock);

  index_t last_commit_index = _last_commit_index;
  // 1. Reply false if term < currentTerm (§5.1)
  if (this->term() > term) {
    LOG_TOPIC(WARN, Logger::AGENCY) << "I have a higher term than RPC caller.";
    return false;
  }

  // 2. Reply false if log doesn’t contain an entry at prevLogIndex
  //    whose term matches prevLogTerm (§5.3)
  if (!_state.find(prevIndex,prevTerm)) {
    LOG_TOPIC(WARN, Logger::AGENCY)
      << "Unable to find matching entry to previous entry (index,term) = ("
      << prevIndex << "," << prevTerm << ")";
    //return false;
  }

  // 3. If an existing entry conflicts with a new one (same index
  //    but different terms), delete the existing entry and all that
  //    follow it (§5.3)
  // 4. Append any new entries not already in the log
  if (queries->slice().length()) {
    LOG_TOPIC(INFO, Logger::AGENCY) << "Appending "<< queries->slice().length()
                                    << " entries to state machine.";
    /* bool success = */_state.log (queries, term, leaderId, prevIndex, prevTerm);
  } else {
    // heart-beat
  }

  // appendEntries 5. If leaderCommit > commitIndex, set commitIndex =
  //min(leaderCommit, index of last new entry)
  if (leaderCommitIndex > last_commit_index) {
    _last_commit_index = (std::min)(leaderCommitIndex,last_commit_index);
  }

  return true;

}

// Leader's append entries
append_entries_t Agent::sendAppendEntriesRPC (id_t follower_id) {

  index_t last_confirmed = _confirmed[follower_id];
  std::vector<log_t> unconfirmed = _state.get(last_confirmed);

  MUTEX_LOCKER(mutexLocker, _ioLock);

  term_t t = this->term();

  // RPC path
  std::stringstream path;
  path << "/_api/agency_priv/appendEntries?term=" << t << "&leaderId="
       << id() << "&prevLogIndex=" << unconfirmed[0].index << "&prevLogTerm="
       << unconfirmed[0].term << "&leaderCommit=" << _last_commit_index;

  // Headers
	std::unique_ptr<std::map<std::string, std::string>> headerFields =
	  std::make_unique<std::map<std::string, std::string> >();

  // Body
  Builder builder;
  index_t last = unconfirmed[0].index;
  builder.add(VPackValue(VPackValueType::Array));
  for (size_t i = 1; i < unconfirmed.size(); ++i) {
    builder.add (VPackValue(VPackValueType::Object));
    builder.add ("index", VPackValue(unconfirmed[i].index));
    builder.add ("query", VPackSlice(unconfirmed[i].entry->data()));
    builder.close();
    last = unconfirmed[i].index;
  }
  builder.close();

  // Send request
  if (unconfirmed.size() > 1) {
    LOG_TOPIC(INFO, Logger::AGENCY)
      << "Appending " << unconfirmed.size()-1 << " entries up to index " << last
      << " to follower " << follower_id;
  }

  arangodb::ClusterComm::instance()->asyncRequest
    ("1", 1, _config.end_points[follower_id],
     arangodb::GeneralRequest::RequestType::POST,
     path.str(), std::make_shared<std::string>(builder.toJson()), headerFields,
     std::make_shared<AgentCallback>(this, follower_id, last),
     0, true);

  return append_entries_t(t, true);

}

// @brief load persistent state
bool Agent::load () {
  TRI_vocbase_t* vocbase =
      TRI_UseDatabaseServer(_server, TRI_VOC_SYSTEM_DATABASE);

  if (vocbase == nullptr) {
    LOG(FATAL) << "could not determine _system database";
    FATAL_ERROR_EXIT();
  }

  _vocbase = vocbase;

  LOG_TOPIC(INFO, Logger::AGENCY) << "Loading persistent state.";
  if (!_state.loadCollections(_vocbase, _applicationV8, _queryRegistry)) {
    LOG_TOPIC(WARN, Logger::AGENCY) << "Failed to load persistent state on statup.";
  }

  LOG_TOPIC(INFO, Logger::AGENCY) << "Reassembling spearhead and read stores.";
//  _read_db.apply(_state.slices());
  _spearhead.apply(_state.slices(_last_commit_index+1));

  LOG_TOPIC(INFO, Logger::AGENCY) << "Starting spearhead worker.";
  _spearhead.start(this);
  _read_db.start(this);

  LOG_TOPIC(INFO, Logger::AGENCY) << "Starting constituent personality.";
  _constituent.start(_vocbase, _applicationV8, _queryRegistry);

  return true;
}

// Write new entries to replicated state and store
write_ret_t Agent::write (query_t const& query)  {

  if (_constituent.leading()) {                    // Only working as leader

    std::vector<bool> applied;
    std::vector<index_t> indices;
    index_t maxind = 0;

    {
      MUTEX_LOCKER(mutexLocker, _ioLock);
      applied = _spearhead.apply(query);             // Apply to spearhead
      indices = _state.log (query, applied, term(), id()); // Log w/ indicies
      if (!indices.empty()) {
        maxind = *std::max_element(indices.begin(), indices.end());
      }
      _cv.signal();                                  // Wake up run
    }

    reportIn(0,maxind);

    return write_ret_t(true,id(),applied,indices); // Indices to wait for to rest

  } else {                                         // Else we redirect
    return write_ret_t(false,_constituent.leaderID());
  }
}

// Read from store
read_ret_t Agent::read (query_t const& query) const {
  if (_constituent.leading()) {     // Only working as leaer
    query_t result = std::make_shared<arangodb::velocypack::Builder>();
    std::vector<bool> success = _read_db.read (query, result);
    return read_ret_t(true, _constituent.leaderID(), success, result);
  } else {                          // Else We redirect
    return read_ret_t(false, _constituent.leaderID());
  }
}

// Repeated append entries
void Agent::run() {

  CONDITION_LOCKER(guard, _cv);

  while (!this->isStopping()) {

    if (leading())
      _cv.wait(250000); // Only if leading
    else
      _cv.wait();       // Just sit there doing nothing

    // Collect all unacknowledged
    for (id_t i = 0; i < size(); ++i) {
      if (i != id()) {
        sendAppendEntriesRPC(i);
      }
    }
  }

}

// Orderly shutdown
void Agent::beginShutdown() {

  // Personal hygiene
  Thread::beginShutdown();

  // Stop constituent and key value stores
  _constituent.beginShutdown();
  _spearhead.beginShutdown();
  _read_db.beginShutdown();

  // Wake up all waiting REST handler (waitFor)
  CONDITION_LOCKER(guard, _cv);
  guard.broadcast();

  if (_vocbase != nullptr) {
    TRI_ReleaseDatabaseServer(_server, _vocbase);
  }

}

// Becoming leader
bool Agent::lead () {

  // Key value stores
  rebuildDBs();

  // Wake up run
  _cv.signal();

  return true;
}

// Rebuild key value stores
bool Agent::rebuildDBs() {
  MUTEX_LOCKER(mutexLocker, _ioLock);
  _spearhead.apply(_state.slices());
  _read_db.apply(_state.slices());
  return true;
}

// Last log entry
log_t const& Agent::lastLog() const {
  return _state.lastLog();
}

// Get spearhead
Store const& Agent::spearhead () const {
  return _spearhead;
}

// Get readdb
Store const& Agent::readDB () const {
  return _read_db;
}

}}
<|endoftext|>


<commit_before>//======================================================================
//-----------------------------------------------------------------------
/**
 * @file        cxx_feature_tests.cpp
 * @brief       iutest c++ feature test
 *
 * @author      t.shirayanagi
 * @par         copyright
 * Copyright (C) 2018, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================

//======================================================================
// include
#include "../include/gtest/iutest_spi_switch.hpp"
#include "logger_tests.hpp"

#if IUTEST_HAS_CXX_HDR_ARRAY
#  include <array>  // NOLINT
#endif

#if IUTEST_HAS_NOEXCEPT_FUNCTION_TYPE

namespace
{

int f1()
{
    return 1;
}
int n1() noexcept
{
    return 1;
}
int f2()
{
    return 2;
}
int n2() noexcept
{
    return 2;
}

}   // namespace

IUTEST(NoexceptFounctionType, Assert)
{
    IUTEST_EXPECT_EQ(f1(), n1());
    IUTEST_EXPECT_LE(f1(), n1());
    IUTEST_EXPECT_GE(f1(), n1());
    IUTEST_EXPECT_LT(f1(), n2());
    IUTEST_EXPECT_GT(f2(), n1());
    IUTEST_EXPECT_NE(f1(), n2());
}

IUTEST(NoexceptFounctionType, ExpressionAssert)
{
    IUTEST_EXPECT(f1() == n1());
}

#endif

#if IUTEST_HAS_CXX_HDR_STRING_VIEW

IUTEST(StringView, Compare)
{
    ::std::string_view view = "Hello";
    IUTEST_ASSERT_EQ("Hello", view);
}

IUTEST(StringView, PrintTo)
{
    LogChecker ck("Hello");
    ::std::string_view view = "Hello";
    IUTEST_SUCCEED() << ::iutest::PrintToString(view);
}

#endif

#if IUTEST_HAS_CXX_HDR_OPTIONAL

IUTEST(Optional, Compare)
{
    {
        ::std::optional<int> opt = 0;
        IUTEST_EXPECT_TRUE(opt);
        IUTEST_EXPECT_EQ(0, opt);
    }
    {
        ::std::optional<int> opt = ::std::nullopt;
        IUTEST_EXPECT_FALSE(opt);
        IUTEST_EXPECT_NONFATAL_FAILURE(IUTEST_EXPECT_EQ(1234, opt), "1234");
    }
}

IUTEST(Optional, PrintTo)
{
    {
        LogChecker ck("1234");
        ::std::optional<int> opt = 1234;
        IUTEST_SUCCEED() << ::iutest::PrintToString(opt);
    }
    {
        LogChecker ck("nullopt");
        ::std::optional<int> opt = ::std::nullopt;
        IUTEST_SUCCEED() << ::iutest::PrintToString(opt);
    }
}

#endif

#if IUTEST_HAS_CXX_HDR_VARIANT

IUTEST(Variant, Compare)
{
    {
        ::std::variant<int, float, ::std::string> v1 = 1234;
        ::std::variant<int, float, ::std::string> v2 = 1234;
        IUTEST_EXPECT_EQ(v1, v2);
    }
}

IUTEST(Variant, PrintTo)
{
    {
        LogChecker ck("1234");
        ::std::variant<int, float, ::std::string> v = 1234;
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
    {
        LogChecker ck("test");
        ::std::variant<int, float, ::std::string> v("test");
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
    {
        LogChecker ck("monostate");
        ::std::variant<std::monostate, int, float, std::string> v;
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
    {
        LogChecker ck("valueless_by_exception");
        ::std::variant<int, float, ::std::string> v = 0.2f;
        try
        {
            struct S { operator int() { throw 42; } };
            v.emplace<0>(S());
        }
        catch(...)
        {
        }
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
}

#endif

#if IUTEST_HAS_CXX_HDR_ARRAY

IUTEST(StdArray, PrintTo)
{
    LogChecker ck("3, 1, 4");
    ::std::array<int, 3> ar = { { 3, 1, 4 } };
    IUTEST_SUCCEED() << ::iutest::PrintToString(ar);
}

#endif

#if IUTEST_HAS_CXX_HDR_ANY

//IUTEST(Any, Compare)
//{
//    {
//        ::std::any v1 = 1;
//        ::std::any v2 = 1;
//        IUTEST_EXPECT_EQ(v1, v2);
//    }
//}

IUTEST(Any, PrintTo)
{
    {
        //LogChecker ck("1234");
        ::std::any v = 1234;
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
}

#endif

#if IUTEST_USE_CXX_FILESYSTEM

IUTEST(FileSystem, PathCompare)
{
    {
        ::std::filesystem::path v1 = "a";
        ::std::filesystem::path v2 = "a";
        IUTEST_EXPECT_EQ(v1, v2);
    }
}

IUTEST(FileSystem, PathPrintTo)
{
    {
        LogChecker ck("/cxx_feature_tests.cpp");
        ::std::filesystem::path v = __FILE__;
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
}

IUTEST(FileSystem, StatusCompare)
{
    {
        ::std::filesystem::file_status v1 = ::std::filesystem::status(__FILE__);
        ::std::filesystem::file_status v2 = ::std::filesystem::status(__FILE__);
        IUTEST_EXPECT_EQ(v1, v2);
    }
}

IUTEST(FileSystem, StatusPrintTo)
{
    {
        LogChecker ck("regular: 0");
        ::std::filesystem::file_status v = ::std::filesystem::status(__FILE__);
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
}

IUTEST(FileSystem, SpaceInfoPrintTo)
{
    {
        LogChecker ck("cpacity");
        ::std::filesystem::path path = __FILE__;
        ::std::filesystem::space_info v = ::std::filesystem::space(path.remove_filename());
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
    {
        LogChecker ck("free");
        ::std::filesystem::path path = __FILE__;
        ::std::filesystem::space_info v = ::std::filesystem::space(path.remove_filename());
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
    {
        LogChecker ck("available");
        ::std::filesystem::path path = __FILE__;
        ::std::filesystem::space_info v = ::std::filesystem::space(path.remove_filename());
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
}

IUTEST(FileSystem, DirectoryEntryCompare)
{
    {
        ::std::filesystem::path path = __FILE__;
        ::std::filesystem::directory_entry x = *::std::filesystem::directory_iterator(path.remove_filename());
        ::std::filesystem::directory_entry v1 = x;
        ::std::filesystem::directory_entry v2 = x;
        IUTEST_EXPECT_EQ(v1, v2);
    }
}

IUTEST(FileSystem, DirectoryEntryPrintTo)
{
    {
        ::std::filesystem::path path = __FILE__;
        ::std::filesystem::path directory = path.remove_filename().append("testdata");
        LogChecker ck(directory.generic_string());
        ::std::filesystem::directory_entry x = *::std::filesystem::directory_iterator(directory);
        IUTEST_SUCCEED() << ::iutest::PrintToString(x);
    }
}

IUTEST(FileSystem, DirectoryIteratorPrintTo)
{
    {
        ::std::filesystem::path path = __FILE__;
        ::std::filesystem::path directory = path.remove_filename().append("testdata");
        LogChecker ck(directory.generic_string());
        ::std::filesystem::directory_iterator x = ::std::filesystem::directory_iterator(directory);
        IUTEST_SUCCEED() << ::iutest::PrintToString(x);
    }
}

#endif

#ifdef UNICODE
int wmain(int argc, wchar_t* argv[])
#else
int main(int argc, char* argv[])
#endif
{
    IUTEST_INIT(&argc, argv);
    return IUTEST_RUN_ALL_TESTS();
}
<commit_msg>add nullopt eq test<commit_after>//======================================================================
//-----------------------------------------------------------------------
/**
 * @file        cxx_feature_tests.cpp
 * @brief       iutest c++ feature test
 *
 * @author      t.shirayanagi
 * @par         copyright
 * Copyright (C) 2018, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================

//======================================================================
// include
#include "../include/gtest/iutest_spi_switch.hpp"
#include "logger_tests.hpp"

#if IUTEST_HAS_CXX_HDR_ARRAY
#  include <array>  // NOLINT
#endif

#if IUTEST_HAS_NOEXCEPT_FUNCTION_TYPE

namespace
{

int f1()
{
    return 1;
}
int n1() noexcept
{
    return 1;
}
int f2()
{
    return 2;
}
int n2() noexcept
{
    return 2;
}

}   // namespace

IUTEST(NoexceptFounctionType, Assert)
{
    IUTEST_EXPECT_EQ(f1(), n1());
    IUTEST_EXPECT_LE(f1(), n1());
    IUTEST_EXPECT_GE(f1(), n1());
    IUTEST_EXPECT_LT(f1(), n2());
    IUTEST_EXPECT_GT(f2(), n1());
    IUTEST_EXPECT_NE(f1(), n2());
}

IUTEST(NoexceptFounctionType, ExpressionAssert)
{
    IUTEST_EXPECT(f1() == n1());
}

#endif

#if IUTEST_HAS_CXX_HDR_STRING_VIEW

IUTEST(StringView, Compare)
{
    ::std::string_view view = "Hello";
    IUTEST_ASSERT_EQ("Hello", view);
}

IUTEST(StringView, PrintTo)
{
    LogChecker ck("Hello");
    ::std::string_view view = "Hello";
    IUTEST_SUCCEED() << ::iutest::PrintToString(view);
}

#endif

#if IUTEST_HAS_CXX_HDR_OPTIONAL

IUTEST(Optional, Compare)
{
    {
        ::std::optional<int> opt = 0;
        IUTEST_EXPECT_TRUE(opt);
        IUTEST_EXPECT_EQ(0, opt);
    }
    {
        ::std::optional<int> opt = ::std::nullopt;
        IUTEST_EXPECT_EQ(::std::nullopt, opt);
    }
    {
        ::std::optional<int> opt = ::std::nullopt;
        IUTEST_EXPECT_FALSE(opt);
        IUTEST_EXPECT_NONFATAL_FAILURE(IUTEST_EXPECT_EQ(1234, opt), "1234");
    }
}

IUTEST(Optional, PrintTo)
{
    {
        LogChecker ck("1234");
        ::std::optional<int> opt = 1234;
        IUTEST_SUCCEED() << ::iutest::PrintToString(opt);
    }
    {
        LogChecker ck("nullopt");
        ::std::optional<int> opt = ::std::nullopt;
        IUTEST_SUCCEED() << ::iutest::PrintToString(opt);
    }
}

#endif

#if IUTEST_HAS_CXX_HDR_VARIANT

IUTEST(Variant, Compare)
{
    {
        ::std::variant<int, float, ::std::string> v1 = 1234;
        ::std::variant<int, float, ::std::string> v2 = 1234;
        IUTEST_EXPECT_EQ(v1, v2);
    }
}

IUTEST(Variant, PrintTo)
{
    {
        LogChecker ck("1234");
        ::std::variant<int, float, ::std::string> v = 1234;
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
    {
        LogChecker ck("test");
        ::std::variant<int, float, ::std::string> v("test");
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
    {
        LogChecker ck("monostate");
        ::std::variant<std::monostate, int, float, std::string> v;
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
    {
        LogChecker ck("valueless_by_exception");
        ::std::variant<int, float, ::std::string> v = 0.2f;
        try
        {
            struct S { operator int() { throw 42; } };
            v.emplace<0>(S());
        }
        catch(...)
        {
        }
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
}

#endif

#if IUTEST_HAS_CXX_HDR_ARRAY

IUTEST(StdArray, PrintTo)
{
    LogChecker ck("3, 1, 4");
    ::std::array<int, 3> ar = { { 3, 1, 4 } };
    IUTEST_SUCCEED() << ::iutest::PrintToString(ar);
}

#endif

#if IUTEST_HAS_CXX_HDR_ANY

//IUTEST(Any, Compare)
//{
//    {
//        ::std::any v1 = 1;
//        ::std::any v2 = 1;
//        IUTEST_EXPECT_EQ(v1, v2);
//    }
//}

IUTEST(Any, PrintTo)
{
    {
        //LogChecker ck("1234");
        ::std::any v = 1234;
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
}

#endif

#if IUTEST_USE_CXX_FILESYSTEM

IUTEST(FileSystem, PathCompare)
{
    {
        ::std::filesystem::path v1 = "a";
        ::std::filesystem::path v2 = "a";
        IUTEST_EXPECT_EQ(v1, v2);
    }
}

IUTEST(FileSystem, PathPrintTo)
{
    {
        LogChecker ck("/cxx_feature_tests.cpp");
        ::std::filesystem::path v = __FILE__;
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
}

IUTEST(FileSystem, StatusCompare)
{
    {
        ::std::filesystem::file_status v1 = ::std::filesystem::status(__FILE__);
        ::std::filesystem::file_status v2 = ::std::filesystem::status(__FILE__);
        IUTEST_EXPECT_EQ(v1, v2);
    }
}

IUTEST(FileSystem, StatusPrintTo)
{
    {
        LogChecker ck("regular: 0");
        ::std::filesystem::file_status v = ::std::filesystem::status(__FILE__);
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
}

IUTEST(FileSystem, SpaceInfoPrintTo)
{
    {
        LogChecker ck("cpacity");
        ::std::filesystem::path path = __FILE__;
        ::std::filesystem::space_info v = ::std::filesystem::space(path.remove_filename());
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
    {
        LogChecker ck("free");
        ::std::filesystem::path path = __FILE__;
        ::std::filesystem::space_info v = ::std::filesystem::space(path.remove_filename());
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
    {
        LogChecker ck("available");
        ::std::filesystem::path path = __FILE__;
        ::std::filesystem::space_info v = ::std::filesystem::space(path.remove_filename());
        IUTEST_SUCCEED() << ::iutest::PrintToString(v);
    }
}

IUTEST(FileSystem, DirectoryEntryCompare)
{
    {
        ::std::filesystem::path path = __FILE__;
        ::std::filesystem::directory_entry x = *::std::filesystem::directory_iterator(path.remove_filename());
        ::std::filesystem::directory_entry v1 = x;
        ::std::filesystem::directory_entry v2 = x;
        IUTEST_EXPECT_EQ(v1, v2);
    }
}

IUTEST(FileSystem, DirectoryEntryPrintTo)
{
    {
        ::std::filesystem::path path = __FILE__;
        ::std::filesystem::path directory = path.remove_filename().append("testdata");
        LogChecker ck(directory.generic_string());
        ::std::filesystem::directory_entry x = *::std::filesystem::directory_iterator(directory);
        IUTEST_SUCCEED() << ::iutest::PrintToString(x);
    }
}

IUTEST(FileSystem, DirectoryIteratorPrintTo)
{
    {
        ::std::filesystem::path path = __FILE__;
        ::std::filesystem::path directory = path.remove_filename().append("testdata");
        LogChecker ck(directory.generic_string());
        ::std::filesystem::directory_iterator x = ::std::filesystem::directory_iterator(directory);
        IUTEST_SUCCEED() << ::iutest::PrintToString(x);
    }
}

#endif

#ifdef UNICODE
int wmain(int argc, wchar_t* argv[])
#else
int main(int argc, char* argv[])
#endif
{
    IUTEST_INIT(&argc, argv);
    return IUTEST_RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#pragma once

// generic (non-architecture-specific) implementations of gemmBitserial
// and other related functions

/* Multiply two binary matrices. Note that rhs must be given in transposed
   form, and the result is also produced transposed.
*/
template <typename AccType>
void gemmBinary_generic_naive(uint64_t * A, uint64_t * BT, AccType * CT, AccType alpha,
uint64_t rowsA, uint64_t depth_words, uint64_t rowsBT) {
  for(uint64_t rBT = 0; rBT < rowsBT; rBT++) {
    uint64_t * BTptr = &BT[rBT * depth_words];
    for(uint64_t rA = 0; rA < rowsA; rA++) {
      uint64_t * Aptr = &A[rA * depth_words];
      AccType acc = 0;
      for(uint64_t d = 0; d < depth_words; d++) {
        acc += __builtin_popcountll(Aptr[d] & BTptr[d]);
      }
      CT[rBT * rowsA + rA] += acc * alpha;
    }
  }
}

template <typename AccType>
void gemmBinary_generic_tile2x1x2(uint64_t * A, uint64_t * BT, AccType * CT, AccType alpha,
uint64_t rowsA, uint64_t depth_words, uint64_t rowsBT) {
  const uint64_t Atile = 2, DepthTile = 1, BTtile = 2;
  const size_t num_acc = Atile*BTtile;
  assert(rowsA % Atile == 0);
  assert(depth_words % DepthTile == 0);
  assert(rowsBT % BTtile == 0);

  for(uint64_t rBT = 0; rBT < rowsBT; rBT += BTtile) {
    uint64_t * BTptr = &BT[rBT * depth_words];
    for(uint64_t rA = 0; rA < rowsA; rA += Atile) {
      uint64_t * Aptr = &A[rA * depth_words];
      AccType acc[num_acc] = {0};
      for(uint64_t d = 0; d < depth_words; d += DepthTile) {
        const uint64_t a0 = Aptr[d], a1 = Aptr[d + depth_words];
        const uint64_t b0 = BTptr[d], b1 = BTptr[d + depth_words];
        acc[0] += __builtin_popcountll(a0 & b0);
        acc[1] += __builtin_popcountll(a0 & b1);
        acc[2] += __builtin_popcountll(a1 & b0);
        acc[3] += __builtin_popcountll(a1 & b1);
      }
      for(uint64_t at = 0; at < Atile; at++) {
        for(uint64_t bt = 0; bt < BTtile; bt++) {
          CT[(rBT + bt) * rowsA + (rA + at)] += acc[at * BTtile + bt] * alpha;
        }
      }
    }
  }
}

/* Bit-serial GEMM via a series of calls to gemmBinary.
   Note that rhs must be given in transposed form, and the result is also
   produced transposed.
*/
template <typename AccType>
void gemmBitSerial_generic_usingBinary(BitSerialMatrix * lhs, BitSerialMatrix * rhs, AccType * res) {
  // ensure that matrix shapes are compatible
  assert(lhs->ncols == rhs->ncols);
  const uint64_t lhsbits = lhs->nbits;
  const uint64_t rhsbits = rhs->nbits;
  // clear contents of result matrix by setting everything to zero
  memset(res, 0, lhs->nrows*rhs->nrows*sizeof(AccType));
  // call binary GEMM for each bit position
  for(uint64_t lbit = 0; lbit < lhsbits; lbit++) {
    bool neg_lhs = lhs->issigned && (lbit == lhsbits-1);
    for(uint64_t rbit = 0; rbit < rhsbits; rbit++) {
      bool neg_rhs = rhs->issigned && (rbit == rhsbits-1);
      bool neg = neg_rhs ^ neg_lhs;
      AccType alpha = neg ? -(1 << (lbit+rbit)) : (1 << (lbit+rbit));
      if(lhs->nrows % 2 == 0 && rhs->nrows % 2 == 0) {
        gemmBinary_generic_tile2x1x2(lhs->bitplaneptr(lbit), rhs->bitplaneptr(rbit), res, alpha, lhs->nrows, lhs->wordsPerRow(), rhs->nrows);
      } else {
        gemmBinary_generic_naive(lhs->bitplaneptr(lbit), rhs->bitplaneptr(rbit), res, alpha, lhs->nrows, lhs->wordsPerRow(), rhs->nrows);
      }
    }
  }
}

/* Standalone bit-serial GEMM. Note that rhs must be given in transposed
   form, and the result is also produced transposed.
*/
template <typename AccType>
void gemmBitSerial_generic_naive(BitSerialMatrix * lhs, BitSerialMatrix * rhs, AccType * res) {
  // ensure that matrix shapes are compatible
  assert(lhs->ncols == rhs->ncols);
  const uint64_t lhsbits = lhs->nbits;
  const uint64_t rhsbits = rhs->nbits;
  const uint64_t out_rows = lhs->nrows;
  const uint64_t out_cols = rhs->nrows;
  const uint64_t depth = lhs->wordsPerRow();

  for(uint64_t i = 0; i < out_cols; i++) {
    for(uint64_t j = 0; j < out_rows; j++) {
      AccType rowres = 0;
      for(uint64_t lbit = 0; lbit < lhsbits; lbit++) {
        bool neg_lhs = lhs->issigned && (lbit == lhsbits-1);
        for(uint64_t rbit = 0; rbit < rhsbits; rbit++) {
          bool neg_rhs = rhs->issigned && (rbit == rhsbits-1);
          uint64_t * ldata = lhs->rowptr(lbit, j);
          uint64_t * rdata = rhs->rowptr(rbit, i);
          uint64_t andcard = 0;
          // AND-popcount-accumulate over row pair
          for(uint64_t k = 0; k < depth; k++) {
            andcard += __builtin_popcountll(ldata[k] & rdata[k]);
          }
          // scale
          andcard = andcard << (lbit + rbit);
          // negate if needed
          rowres += (neg_lhs ^ neg_rhs) ? -andcard : andcard;
        }
      }
      res[i * out_rows + j] = rowres;
    }
  }
}
<commit_msg>add findBlockSize utility function<commit_after>#pragma once
#include <math.h>

// generic (non-architecture-specific) implementations of gemmBitserial
// and other related functions

/* Utility function to find block size under the following assumptions:
   - size of lhs block + rhs block + result block <= cacheBits
   - no blocking along depth (i.e. only entire rows of dBits bits)
   - lhsMult and rhsMult determine the ratio for lhs and rhs rows in cache
   - returned lhsRows and rhsRows are divisible by lhsMult and rhsMult, respectively
   - each result elem takes bitsPerRes bits
*/
void findBlockSize(float cacheBits, float dBits, float lhsMult, float rhsMult,
  float bitsPerRes, uint64_t & lhsRows, uint64_t & rhsRows) {
  float a = bitsPerRes * lhsMult * rhsMult;
  float b = dBits*(lhsMult + rhsMult);
  float c = -cacheBits;
  float discr = sqrt(b*b - 4 * a * c);
  assert(discr > 0);
  int64_t x0 = floor((-b + discr) / (2*a));
  int64_t x1 = floor((-b - discr) / (2*a));
  int64_t x = x0 > x1 ? x0 : x1;
  assert(x > 0);
  lhsRows = lhsMult * x;
  rhsRows = rhsMult * x;
}

/* Multiply two binary matrices. Note that rhs must be given in transposed
   form, and the result is also produced transposed.
*/
template <typename AccType>
void gemmBinary_generic_naive(uint64_t * A, uint64_t * BT, AccType * CT, AccType alpha,
uint64_t rowsA, uint64_t depth_words, uint64_t rowsBT) {
  for(uint64_t rBT = 0; rBT < rowsBT; rBT++) {
    uint64_t * BTptr = &BT[rBT * depth_words];
    for(uint64_t rA = 0; rA < rowsA; rA++) {
      uint64_t * Aptr = &A[rA * depth_words];
      AccType acc = 0;
      for(uint64_t d = 0; d < depth_words; d++) {
        acc += __builtin_popcountll(Aptr[d] & BTptr[d]);
      }
      CT[rBT * rowsA + rA] += acc * alpha;
    }
  }
}

template <typename AccType>
void gemmBinary_generic_tile2x1x2(uint64_t * A, uint64_t * BT, AccType * CT, AccType alpha,
uint64_t rowsA, uint64_t depth_words, uint64_t rowsBT) {
  const uint64_t Atile = 2, DepthTile = 1, BTtile = 2;
  const size_t num_acc = Atile*BTtile;
  assert(rowsA % Atile == 0);
  assert(depth_words % DepthTile == 0);
  assert(rowsBT % BTtile == 0);

  for(uint64_t rBT = 0; rBT < rowsBT; rBT += BTtile) {
    uint64_t * BTptr = &BT[rBT * depth_words];
    for(uint64_t rA = 0; rA < rowsA; rA += Atile) {
      uint64_t * Aptr = &A[rA * depth_words];
      AccType acc[num_acc] = {0};
      for(uint64_t d = 0; d < depth_words; d += DepthTile) {
        const uint64_t a0 = Aptr[d], a1 = Aptr[d + depth_words];
        const uint64_t b0 = BTptr[d], b1 = BTptr[d + depth_words];
        acc[0] += __builtin_popcountll(a0 & b0);
        acc[1] += __builtin_popcountll(a0 & b1);
        acc[2] += __builtin_popcountll(a1 & b0);
        acc[3] += __builtin_popcountll(a1 & b1);
      }
      for(uint64_t at = 0; at < Atile; at++) {
        for(uint64_t bt = 0; bt < BTtile; bt++) {
          CT[(rBT + bt) * rowsA + (rA + at)] += acc[at * BTtile + bt] * alpha;
        }
      }
    }
  }
}

/* Bit-serial GEMM via a series of calls to gemmBinary.
   Note that rhs must be given in transposed form, and the result is also
   produced transposed.
*/
template <typename AccType>
void gemmBitSerial_generic_usingBinary(BitSerialMatrix * lhs, BitSerialMatrix * rhs, AccType * res) {
  // ensure that matrix shapes are compatible
  assert(lhs->ncols == rhs->ncols);
  const uint64_t lhsbits = lhs->nbits;
  const uint64_t rhsbits = rhs->nbits;
  // clear contents of result matrix by setting everything to zero
  memset(res, 0, lhs->nrows*rhs->nrows*sizeof(AccType));
  // call binary GEMM for each bit position
  for(uint64_t lbit = 0; lbit < lhsbits; lbit++) {
    bool neg_lhs = lhs->issigned && (lbit == lhsbits-1);
    for(uint64_t rbit = 0; rbit < rhsbits; rbit++) {
      bool neg_rhs = rhs->issigned && (rbit == rhsbits-1);
      bool neg = neg_rhs ^ neg_lhs;
      AccType alpha = neg ? -(1 << (lbit+rbit)) : (1 << (lbit+rbit));
      if(lhs->nrows % 2 == 0 && rhs->nrows % 2 == 0) {
        gemmBinary_generic_tile2x1x2(lhs->bitplaneptr(lbit), rhs->bitplaneptr(rbit), res, alpha, lhs->nrows, lhs->wordsPerRow(), rhs->nrows);
      } else {
        gemmBinary_generic_naive(lhs->bitplaneptr(lbit), rhs->bitplaneptr(rbit), res, alpha, lhs->nrows, lhs->wordsPerRow(), rhs->nrows);
      }
    }
  }
}

/* Standalone bit-serial GEMM. Note that rhs must be given in transposed
   form, and the result is also produced transposed.
*/
template <typename AccType>
void gemmBitSerial_generic_naive(BitSerialMatrix * lhs, BitSerialMatrix * rhs, AccType * res) {
  // ensure that matrix shapes are compatible
  assert(lhs->ncols == rhs->ncols);
  const uint64_t lhsbits = lhs->nbits;
  const uint64_t rhsbits = rhs->nbits;
  const uint64_t out_rows = lhs->nrows;
  const uint64_t out_cols = rhs->nrows;
  const uint64_t depth = lhs->wordsPerRow();

  for(uint64_t i = 0; i < out_cols; i++) {
    for(uint64_t j = 0; j < out_rows; j++) {
      AccType rowres = 0;
      for(uint64_t lbit = 0; lbit < lhsbits; lbit++) {
        bool neg_lhs = lhs->issigned && (lbit == lhsbits-1);
        for(uint64_t rbit = 0; rbit < rhsbits; rbit++) {
          bool neg_rhs = rhs->issigned && (rbit == rhsbits-1);
          uint64_t * ldata = lhs->rowptr(lbit, j);
          uint64_t * rdata = rhs->rowptr(rbit, i);
          uint64_t andcard = 0;
          // AND-popcount-accumulate over row pair
          for(uint64_t k = 0; k < depth; k++) {
            andcard += __builtin_popcountll(ldata[k] & rdata[k]);
          }
          // scale
          andcard = andcard << (lbit + rbit);
          // negate if needed
          rowres += (neg_lhs ^ neg_rhs) ? -andcard : andcard;
        }
      }
      res[i * out_rows + j] = rowres;
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "google/cloud/storage/client.h"
#include "google/cloud/storage/testing/object_integration_test.h"
#include "google/cloud/internal/getenv.h"
#include "google/cloud/status.h"
#include "google/cloud/status_or.h"
#include "google/cloud/testing_util/scoped_environment.h"
#include "google/cloud/testing_util/status_matchers.h"
#include <gmock/gmock.h>

namespace google {
namespace cloud {
namespace storage {
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
namespace {

using ::google::cloud::testing_util::ScopedEnvironment;
using ::google::cloud::testing_util::StatusIs;
using ::testing::HasSubstr;
using ::testing::Not;

using ErrorParsingIntegrationTest =
    ::google::cloud::storage::testing::ObjectIntegrationTest;

TEST_F(ErrorParsingIntegrationTest, FailureContainsErrorInfo) {
  // TODO(#9947) - enable with new implementation once fixed.
  ScopedEnvironment env("GOOGLE_CLOUD_CPP_STORAGE_USE_LEGACY_HTTP", "any");
  StatusOr<Client> client = MakeIntegrationTestClient();
  ASSERT_STATUS_OK(client);

  auto object_name = MakeRandomObjectName();

  // Start a resumable upload and finalize the upload.
  auto insert = client->InsertObject(bucket_name_, object_name, LoremIpsum(),
                                     IfGenerationMatch(0));
  ASSERT_THAT(insert, StatusIs(StatusCode::kOk));
  ScheduleForDelete(*insert);

  // Overwrite the object.
  insert = client->InsertObject(bucket_name_, object_name, LoremIpsum(),
                                IfGenerationMatch(0));
  ASSERT_THAT(insert, Not(StatusIs(StatusCode::kOk)));
  if (UsingEmulator()) return;
  EXPECT_THAT(insert.status().message(),
              HasSubstr("pre-conditions you specified did not hold"));
}

}  // anonymous namespace
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
}  // namespace storage
}  // namespace cloud
}  // namespace google
<commit_msg>test(storage): check for useful `ErrorInfo` (#9974)<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "google/cloud/storage/client.h"
#include "google/cloud/storage/testing/object_integration_test.h"
#include "google/cloud/internal/getenv.h"
#include "google/cloud/status.h"
#include "google/cloud/status_or.h"
#include "google/cloud/testing_util/scoped_environment.h"
#include "google/cloud/testing_util/status_matchers.h"
#include <gmock/gmock.h>

namespace google {
namespace cloud {
namespace storage {
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
namespace {

using ::google::cloud::testing_util::ScopedEnvironment;
using ::google::cloud::testing_util::StatusIs;
using ::testing::HasSubstr;
using ::testing::IsEmpty;
using ::testing::Not;

using ErrorParsingIntegrationTest =
    ::google::cloud::storage::testing::ObjectIntegrationTest;

TEST_F(ErrorParsingIntegrationTest, FailureContainsErrorInfo) {
  // TODO(#9947) - enable with new implementation once fixed.
  ScopedEnvironment env("GOOGLE_CLOUD_CPP_STORAGE_USE_LEGACY_HTTP", "any");
  StatusOr<Client> client = MakeIntegrationTestClient();
  ASSERT_STATUS_OK(client);

  auto object_name = MakeRandomObjectName();

  // Start a resumable upload and finalize the upload.
  auto insert = client->InsertObject(bucket_name_, object_name, LoremIpsum(),
                                     IfGenerationMatch(0));
  ASSERT_THAT(insert, StatusIs(StatusCode::kOk));
  ScheduleForDelete(*insert);

  // Overwrite the object.
  insert = client->InsertObject(bucket_name_, object_name, LoremIpsum(),
                                IfGenerationMatch(0));
  ASSERT_THAT(insert, Not(StatusIs(StatusCode::kOk)));
  if (UsingEmulator() || UsingGrpc()) return;
  EXPECT_THAT(insert.status().message(),
              HasSubstr("pre-conditions you specified did not hold"));
  auto const& error_info = insert.status().error_info();
  EXPECT_THAT(error_info.reason(), Not(IsEmpty()));
  EXPECT_THAT(error_info.domain(), Not(IsEmpty()));
  EXPECT_THAT(error_info.metadata(), Not(IsEmpty()));
}

}  // anonymous namespace
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
}  // namespace storage
}  // namespace cloud
}  // namespace google
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* 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.                   *
*******************************************************************************
*                            SOFA :: Applications                             *
*                                                                             *
* Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
* H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
* M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/

#include "SofaTutorialManager.h"

#include <sofa/helper/system/FileRepository.h>
#include <sofa/helper/system/SetDirectory.h>

#ifdef SOFA_QT4
#include <QHBoxLayout>
#include <QUrl>
#include <QMenuBar>
#else
#include <qlayout.h>
#include <qurl.h>
#endif

namespace sofa
{

namespace gui
{

namespace qt
{

SofaTutorialManager::SofaTutorialManager(QWidget* parent, const char* name):QMainWindow(parent, name)
{

    QWidget *mainWidget = new QWidget(this);
    QHBoxLayout *mainLayout = new QHBoxLayout(mainWidget);
    this->setCentralWidget(mainWidget);
    this->setAcceptDrops(TRUE);
    this->setCaption(QString("Sofa Tutorials"));

    std::string fileTutorials="config/tutorials.xml";
    fileTutorials = sofa::helper::system::DataRepository.getFile( fileTutorials );

    //Create the tree containing the tutorials
    selector = new TutorialSelector(fileTutorials, mainWidget);
    connect(selector, SIGNAL(openTutorial(const std::string&)),
            this, SLOT(openTutorial(const std::string&)));
    connect(selector, SIGNAL(openHTML(const std::string&)),
            this, SLOT(openHTML(const std::string&)));

    //Create the HTML Browser to display the information
    descriptionPage = new QTextBrowser(mainWidget);
#ifdef SOFA_QT4
    connect(descriptionPage, SIGNAL(anchorClicked(const QUrl&)), this, SLOT(dynamicChangeOfScene(const QUrl&)));
#else
    // QMimeSourceFactory::defaultFactory()->setExtensionType("html", "text/utf8");
    descriptionPage->mimeSourceFactory()->setExtensionType("html", "text/utf8");;
    connect(descriptionPage, SIGNAL(linkClicked(const QString&)), this, SLOT(dynamicChangeOfScene(const QString&)));
#endif
    descriptionPage->setMinimumWidth(400);
    //Create the Graph
    graph = new GraphModeler(mainWidget);
    graph->setAcceptDrops(true);

#ifdef SOFA_QT4
    //Create the Menu bar
    QMenuBar *menuBar = this->menuBar();
    menuBar->setEnabled(true);

    runInSofaAction = new QAction(this);
    runInSofaAction->setText("Launch scene in Sofa");
    runInSofaAction->setAccel(QKeySequence(tr("Ctrl+R")));
    menuBar->addAction(runInSofaAction);
    connect(runInSofaAction, SIGNAL(activated()), this, SLOT(launchScene()));

    QAction *undoAction = new QAction(this);
    undoAction->setAccel(QKeySequence(tr("Ctrl+Z")));
    menuBar->addAction(undoAction);
    connect(undoAction, SIGNAL(activated()), graph, SLOT(editUndo()));

    QAction *redoAction = new QAction(this);
    redoAction->setAccel(QKeySequence(tr("Ctrl+Y")));
    menuBar->addAction(redoAction);
    connect(redoAction, SIGNAL(activated()), graph, SLOT(editRedo()));
#else
    QToolBar *toolBar = new QToolBar( QString(""), this, DockTop);
    toolBar->setLabel(QString("Tools"));

    buttonRunInSofa = new QPushButton(QString("Launch scene in Sofa"), toolBar);
    connect(buttonRunInSofa, SIGNAL(clicked()), this, SLOT(launchScene()));

    runInSofaAction = new QAction(this);
    runInSofaAction->setText("Launch scene in Sofa");
    runInSofaAction->setAccel(QKeySequence(tr("Ctrl+R")));
    connect(runInSofaAction, SIGNAL(activated()), this, SLOT(launchScene()));

    QAction *undoAction = new QAction(this);
    undoAction->setAccel(QKeySequence(tr("Ctrl+Z")));
    connect(undoAction, SIGNAL(activated()), graph, SLOT(editUndo()));

    QAction *redoAction = new QAction(this);
    redoAction->setAccel(QKeySequence(tr("Ctrl+Y")));
    connect(redoAction, SIGNAL(activated()), graph, SLOT(editRedo()));
#endif

    //Setup the layout
    mainLayout->addWidget(selector);
    mainLayout->addWidget(descriptionPage);
    mainLayout->addWidget(graph);

    this->resize(1000,600);
    this->setPaletteBackgroundColor(QColor(255,180,120));
    openHTML("");

    QString pathIcon=(sofa::helper::system::DataRepository.getFirstPath() + std::string( "/icons/SOFATUTORIALS.png" )).c_str();
#ifdef SOFA_QT4
    this->setWindowIcon(QIcon(pathIcon));
#else
    this->setIcon(QPixmap(pathIcon));
#endif
}

void SofaTutorialManager::openTutorial(const std::string& filename)
{
    if (filename.empty()) return;

    std::string file(sofa::helper::system::SetDirectory::GetFileName(filename.c_str()));
    runInSofaAction->setText(QString("Launch ")+QString(file.c_str()) + QString(" in Sofa"));
#ifndef SOFA_QT4
    buttonRunInSofa->setText(QString("Launch ")+QString(file.c_str()) + QString(" in Sofa"));
#endif

    //Set the Graph
    xml::BaseElement* newXML = xml::loadFromFile ( filename.c_str() );
    if (newXML == NULL) return;
    if (!newXML->init()) std::cerr<< "Objects initialization failed.\n";
    GNode *root = dynamic_cast<GNode*> ( newXML->getObject() );
    graph->setRoot(root, false);
    graph->setFilename(filename);
}

void SofaTutorialManager::openHTML(const std::string &filename)
{
    if (filename.empty())
    {
#ifdef WIN32
        static std::string defaultHTML("file:///"+sofa::helper::system::SetDirectory::GetProcessFullPath(sofa::helper::system::DataRepository.getFile( "Tutorials/Tutorials.html" ).c_str()));
#else
        static std::string defaultHTML(sofa::helper::system::SetDirectory::GetProcessFullPath(sofa::helper::system::DataRepository.getFile( "Tutorials/Tutorials.html" ).c_str()));
#endif
        openHTML(defaultHTML);
        return;
    }

#ifdef SOFA_QT4
#ifdef WIN32
    descriptionPage->setSource(QUrl(QString("file:///")+QString(filename.c_str())));
#else
    descriptionPage->setSource(QUrl(QString(filename.c_str())));
#endif
#else
    descriptionPage->mimeSourceFactory()->setFilePath(QString(filename.c_str()));
    descriptionPage->setSource(QString(filename.c_str()));
#endif
}

#ifdef SOFA_QT4
void SofaTutorialManager::dynamicChangeOfScene( const QUrl& u)
{
    std::string path=u.path().ascii();
#ifdef WIN32
    path = path.substr(1);
#endif
#else
void SofaTutorialManager::dynamicChangeOfScene( const QString& u)
{
    std::string path=u.ascii();
#endif
    path  = sofa::helper::system::DataRepository.getFile(path);
    std::string extension=sofa::helper::system::SetDirectory::GetExtension(path.c_str());
    if (extension == "xml" || extension == "scn")
    {
        openTutorial(path);
        std::string htmlLink=path.substr(0,path.size()-3)+"html";
        if (sofa::helper::system::DataRepository.findFile(htmlLink))
            openHTML(htmlLink);
        else
            openHTML("");
    }
    else if (extension == "html")
    {
        openHTML(path);
    }
}

void SofaTutorialManager::launchScene()
{
    emit runInSofa(graph->getFilename(), graph->getRoot());
}

}
}
}
<commit_msg>r6780/sofa-dev : FIX: should be the last fix for windows...<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* 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.                   *
*******************************************************************************
*                            SOFA :: Applications                             *
*                                                                             *
* Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
* H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
* M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/

#include "SofaTutorialManager.h"

#include <sofa/helper/system/FileRepository.h>
#include <sofa/helper/system/SetDirectory.h>

#ifdef SOFA_QT4
#include <QHBoxLayout>
#include <QUrl>
#include <QMenuBar>
#else
#include <qlayout.h>
#include <qurl.h>
#endif

namespace sofa
{

namespace gui
{

namespace qt
{

SofaTutorialManager::SofaTutorialManager(QWidget* parent, const char* name):QMainWindow(parent, name)
{

    QWidget *mainWidget = new QWidget(this);
    QHBoxLayout *mainLayout = new QHBoxLayout(mainWidget);
    this->setCentralWidget(mainWidget);
    this->setAcceptDrops(TRUE);
    this->setCaption(QString("Sofa Tutorials"));

    std::string fileTutorials="config/tutorials.xml";
    fileTutorials = sofa::helper::system::DataRepository.getFile( fileTutorials );

    //Create the tree containing the tutorials
    selector = new TutorialSelector(fileTutorials, mainWidget);
    connect(selector, SIGNAL(openTutorial(const std::string&)),
            this, SLOT(openTutorial(const std::string&)));
    connect(selector, SIGNAL(openHTML(const std::string&)),
            this, SLOT(openHTML(const std::string&)));

    //Create the HTML Browser to display the information
    descriptionPage = new QTextBrowser(mainWidget);
#ifdef SOFA_QT4
    connect(descriptionPage, SIGNAL(anchorClicked(const QUrl&)), this, SLOT(dynamicChangeOfScene(const QUrl&)));
#else
    // QMimeSourceFactory::defaultFactory()->setExtensionType("html", "text/utf8");
    descriptionPage->mimeSourceFactory()->setExtensionType("html", "text/utf8");;
    connect(descriptionPage, SIGNAL(linkClicked(const QString&)), this, SLOT(dynamicChangeOfScene(const QString&)));
#endif
    descriptionPage->setMinimumWidth(400);
    //Create the Graph
    graph = new GraphModeler(mainWidget);
    graph->setAcceptDrops(true);

#ifdef SOFA_QT4
    //Create the Menu bar
    QMenuBar *menuBar = this->menuBar();
    menuBar->setEnabled(true);

    runInSofaAction = new QAction(this);
    runInSofaAction->setText("Launch scene in Sofa");
    runInSofaAction->setAccel(QKeySequence(tr("Ctrl+R")));
    menuBar->addAction(runInSofaAction);
    connect(runInSofaAction, SIGNAL(activated()), this, SLOT(launchScene()));

    QAction *undoAction = new QAction(this);
    undoAction->setAccel(QKeySequence(tr("Ctrl+Z")));
    menuBar->addAction(undoAction);
    connect(undoAction, SIGNAL(activated()), graph, SLOT(editUndo()));

    QAction *redoAction = new QAction(this);
    redoAction->setAccel(QKeySequence(tr("Ctrl+Y")));
    menuBar->addAction(redoAction);
    connect(redoAction, SIGNAL(activated()), graph, SLOT(editRedo()));
#else
    QToolBar *toolBar = new QToolBar( QString(""), this, DockTop);
    toolBar->setLabel(QString("Tools"));

    buttonRunInSofa = new QPushButton(QString("Launch scene in Sofa"), toolBar);
    connect(buttonRunInSofa, SIGNAL(clicked()), this, SLOT(launchScene()));

    runInSofaAction = new QAction(this);
    runInSofaAction->setText("Launch scene in Sofa");
    runInSofaAction->setAccel(QKeySequence(tr("Ctrl+R")));
    connect(runInSofaAction, SIGNAL(activated()), this, SLOT(launchScene()));

    QAction *undoAction = new QAction(this);
    undoAction->setAccel(QKeySequence(tr("Ctrl+Z")));
    connect(undoAction, SIGNAL(activated()), graph, SLOT(editUndo()));

    QAction *redoAction = new QAction(this);
    redoAction->setAccel(QKeySequence(tr("Ctrl+Y")));
    connect(redoAction, SIGNAL(activated()), graph, SLOT(editRedo()));
#endif

    //Setup the layout
    mainLayout->addWidget(selector);
    mainLayout->addWidget(descriptionPage);
    mainLayout->addWidget(graph);

    this->resize(1000,600);
    this->setPaletteBackgroundColor(QColor(255,180,120));
    openHTML("");

    QString pathIcon=(sofa::helper::system::DataRepository.getFirstPath() + std::string( "/icons/SOFATUTORIALS.png" )).c_str();
#ifdef SOFA_QT4
    this->setWindowIcon(QIcon(pathIcon));
#else
    this->setIcon(QPixmap(pathIcon));
#endif
}

void SofaTutorialManager::openTutorial(const std::string& filename)
{
    if (filename.empty()) return;

    std::string file(sofa::helper::system::SetDirectory::GetFileName(filename.c_str()));
    runInSofaAction->setText(QString("Launch ")+QString(file.c_str()) + QString(" in Sofa"));
#ifndef SOFA_QT4
    buttonRunInSofa->setText(QString("Launch ")+QString(file.c_str()) + QString(" in Sofa"));
#endif

    //Set the Graph
    xml::BaseElement* newXML = xml::loadFromFile ( filename.c_str() );
    if (newXML == NULL) return;
    if (!newXML->init()) std::cerr<< "Objects initialization failed.\n";
    GNode *root = dynamic_cast<GNode*> ( newXML->getObject() );
    graph->setRoot(root, false);
    graph->setFilename(filename);
}

void SofaTutorialManager::openHTML(const std::string &filename)
{
    if (filename.empty())
    {
        static std::string defaultHTML(sofa::helper::system::SetDirectory::GetProcessFullPath(sofa::helper::system::DataRepository.getFile( "Tutorials/Tutorials.html" ).c_str()));
        openHTML(defaultHTML);
        return;
    }

#ifdef SOFA_QT4
#ifdef WIN32
    descriptionPage->setSource(QUrl(QString("file:///")+QString(filename.c_str())));
#else
    descriptionPage->setSource(QUrl(QString(filename.c_str())));
#endif
#else
    descriptionPage->mimeSourceFactory()->setFilePath(QString(filename.c_str()));
    descriptionPage->setSource(QString(filename.c_str()));
#endif
}

#ifdef SOFA_QT4
void SofaTutorialManager::dynamicChangeOfScene( const QUrl& u)
{
    std::string path=u.path().ascii();
#ifdef WIN32
    path = path.substr(1);
#endif
#else
void SofaTutorialManager::dynamicChangeOfScene( const QString& u)
{
    std::string path=u.ascii();
#endif
    path  = sofa::helper::system::DataRepository.getFile(path);
    std::string extension=sofa::helper::system::SetDirectory::GetExtension(path.c_str());
    if (extension == "xml" || extension == "scn")
    {
        openTutorial(path);
        std::string htmlLink=path.substr(0,path.size()-3)+"html";
        if (sofa::helper::system::DataRepository.findFile(htmlLink))
            openHTML(htmlLink);
        else
            openHTML("");
    }
    else if (extension == "html")
    {
        openHTML(path);
    }
}

void SofaTutorialManager::launchScene()
{
    emit runInSofa(graph->getFilename(), graph->getRoot());
}

}
}
}
<|endoftext|>


<commit_before>#include <exception>
#include <functional>
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
//#include "TupleHelpers.h"

class xUnitAssert : std::exception
{
public:
    xUnitAssert(const std::string &)
    {
    }
};

const class
{
public:
    template<typename T0, typename T1>
    void Equal(T0 t0, T1 t1) const
    {
        if (t0 != t1)
        {
            throw xUnitAssert("");
        }
    }

    template<typename T0, typename T1>
    void NotEqual(T0 t0, T1 t1) const
    {
        if (t0 == t1)
        {
            throw xUnitAssert("");
        }
    }

} Assert;

class xUnit
{
    friend class Register;
public:
    class Register
    {
        // !!! someday, Visual Studio will understand variadic macros
        // when it does, fix this collection

        // !!! should use a macro system to automate this
        template<typename TFn, typename TArg0>
        static std::function<void()> TheoryHelper(TFn &&theory, std::tuple<TArg0> &&t)
        {
            return [&, theory]() { return theory(std::forward<TArg0>(std::get<0>(t))); };
        }

        template<typename TFn, typename TArg0, typename TArg1>
        static std::function<void()> TheoryHelper(TFn &&theory, std::tuple<TArg0, TArg1> &&t)
        {
            return [&, theory]() { return theory(std::forward<TArg0>(std::get<0>(t)),
                                         std::forward<TArg1>(std::get<1>(t))); };
        }

        template<typename TFn, typename TArg0, typename TArg1, typename TArg2>
        static std::function<void()> TheoryHelper(TFn &&theory, std::tuple<TArg0, TArg1, TArg2> &&t)
        {
            return [&, theory]() { return theory(std::forward<TArg0>(std::get<0>(t)),
                                         std::forward<TArg1>(std::get<1>(t)),
                                         std::forward<TArg2>(std::get<2>(t))); };
        }

        template<typename TFn, typename TArg0, typename TArg1, typename TArg2, typename TArg3>
        static std::function<void()> TheoryHelper(TFn &&theory, std::tuple<TArg0, TArg1, TArg2, TArg3> &&t)
        {
            return [&, theory]() { return theory(std::forward<TArg0>(std::get<0>(t)),
                                        std::forward<TArg1>(std::get<1>(t)),
                                        std::forward<TArg2>(std::get<2>(t)),
                                        std::forward<TArg3>(std::get<3>(t))); };
        }

        template<typename TFn, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4>
        static std::function<void()> TheoryHelper(TFn &&theory, std::tuple<TArg0, TArg1, TArg2, TArg3, TArg4> &&t)
        {
            return [&, theory]() { return theory(std::forward<TArg0>(std::get<0>(t)),
                                        std::forward<TArg1>(std::get<1>(t)),
                                        std::forward<TArg2>(std::get<2>(t)),
                                        std::forward<TArg3>(std::get<3>(t)),
                                        std::forward<TArg4>(std::get<4>(t))); };
        }

    public:
        Register(const std::function<void()> &fn)
        {
            xUnit::Instance().mFacts.push_back(fn);
        }

        template<typename TTheory, typename TTheoryData>
        Register(TTheory theory, TTheoryData theoryData)
        {
            std::vector<std::function<void()>> theorySet;

            for (auto t : theoryData())
            {
                theorySet.push_back(TheoryHelper(theory, std::move(t)));
            }

            xUnit::Instance().mTheories.push_back(theorySet);
        }
    };

    static void RunAllTests()
    {
        auto facts = 1;
        auto theories = 1;

        // !!! randomize
        for (auto fact : Instance().mFacts)
        {
            // !!! test runner should be single function
            // to avoid duplicated code
            try
            {
                std::cout << "fact " << facts++ << " of " << Instance().mFacts.size() << std::endl;
                fact();
            }
            catch (xUnitAssert &)
            {
                std::cout << "Caught xUnitAssert." << std::endl;
            }
        }

        // !!! randomize
        for (auto theorySet : Instance().mTheories)
        {
            std::cout << "theory " << theories++ << " of " << Instance().mTheories.size() << std::endl;

            auto instance = 1;

            for (auto theory : theorySet)
            {
                try
                {
                    std::cout << "theory instance " << instance++ << " of " << theorySet.size() << std::endl;
                    theory();
                }
                catch (xUnitAssert &)
                {
                    std::cout << "Caught xUnitAssert." << std::endl;
                }
            }
        }
    }

private:
    static xUnit &Instance()
    {
        static xUnit instance;
        return instance;
    }

    std::vector<std::function<void()>> mFacts;
    std::vector<std::vector<std::function<void()>>> mTheories;
};

#define FACT(fn) \
    void fn(); \
    namespace { namespace fn ## _ns { xUnit::Register reg(&fn); } } \
    void fn()

FACT(FactOk)
{
    Assert.Equal(1, 1);
}

FACT(FactFails)
{
    Assert.Equal(0, 1);
}

void TheoryWorks(int, char, bool);
std::vector<std::tuple<int, char, bool>> DataGen();
namespace { namespace TheoryWorks_ns { xUnit::Register reg(&TheoryWorks, &DataGen); } }

std::vector<std::tuple<int, char, bool>> DataGen()
{
    auto result = std::vector<std::tuple<int, char, bool>>();
    result.push_back(std::make_tuple(1, (char)1, true));
    result.push_back(std::make_tuple(0, (char)1, false));
    result.push_back(std::make_tuple(0, (char)1, true));
    return result;
}

void TheoryWorks(int x, char y, bool equal)
{
    if (equal)
    {
        Assert.Equal(x, y);
    }
    else
    {
        Assert.NotEqual(x, y);
    }
}

int main()
{
    xUnit::RunAllTests();
}
<commit_msg>converted theory into a macro; not ideal, but no macros are<commit_after>#include <exception>
#include <functional>
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
//#include "TupleHelpers.h"

class xUnitAssert : std::exception
{
public:
    xUnitAssert(const std::string &)
    {
    }
};

const class
{
public:
    template<typename T0, typename T1>
    void Equal(T0 t0, T1 t1) const
    {
        if (t0 != t1)
        {
            throw xUnitAssert("");
        }
    }

    template<typename T0, typename T1>
    void NotEqual(T0 t0, T1 t1) const
    {
        if (t0 == t1)
        {
            throw xUnitAssert("");
        }
    }

} Assert;

class xUnit
{
    friend class Register;
public:
    class Register
    {
        // !!! someday, Visual Studio will understand variadic macros
        // when it does, fix this collection

        // !!! should use a macro system to automate this
        template<typename TFn, typename TArg0>
        static std::function<void()> TheoryHelper(TFn &&theory, std::tuple<TArg0> &&t)
        {
            return [&, theory]() { return theory(std::forward<TArg0>(std::get<0>(t))); };
        }

        template<typename TFn, typename TArg0, typename TArg1>
        static std::function<void()> TheoryHelper(TFn &&theory, std::tuple<TArg0, TArg1> &&t)
        {
            return [&, theory]() { return theory(std::forward<TArg0>(std::get<0>(t)),
                                         std::forward<TArg1>(std::get<1>(t))); };
        }

        template<typename TFn, typename TArg0, typename TArg1, typename TArg2>
        static std::function<void()> TheoryHelper(TFn &&theory, std::tuple<TArg0, TArg1, TArg2> &&t)
        {
            return [&, theory]() { return theory(std::forward<TArg0>(std::get<0>(t)),
                                         std::forward<TArg1>(std::get<1>(t)),
                                         std::forward<TArg2>(std::get<2>(t))); };
        }

        template<typename TFn, typename TArg0, typename TArg1, typename TArg2, typename TArg3>
        static std::function<void()> TheoryHelper(TFn &&theory, std::tuple<TArg0, TArg1, TArg2, TArg3> &&t)
        {
            return [&, theory]() { return theory(std::forward<TArg0>(std::get<0>(t)),
                                        std::forward<TArg1>(std::get<1>(t)),
                                        std::forward<TArg2>(std::get<2>(t)),
                                        std::forward<TArg3>(std::get<3>(t))); };
        }

        template<typename TFn, typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4>
        static std::function<void()> TheoryHelper(TFn &&theory, std::tuple<TArg0, TArg1, TArg2, TArg3, TArg4> &&t)
        {
            return [&, theory]() { return theory(std::forward<TArg0>(std::get<0>(t)),
                                        std::forward<TArg1>(std::get<1>(t)),
                                        std::forward<TArg2>(std::get<2>(t)),
                                        std::forward<TArg3>(std::get<3>(t)),
                                        std::forward<TArg4>(std::get<4>(t))); };
        }

    public:
        Register(const std::function<void()> &fn)
        {
            xUnit::Instance().mFacts.push_back(fn);
        }

        template<typename TTheory, typename TTheoryData>
        Register(TTheory theory, TTheoryData theoryData)
        {
            std::vector<std::function<void()>> theorySet;

            for (auto t : theoryData())
            {
                theorySet.push_back(TheoryHelper(theory, std::move(t)));
            }

            xUnit::Instance().mTheories.push_back(theorySet);
        }
    };

    static void RunAllTests()
    {
        auto facts = 1;
        auto theories = 1;

        // !!! randomize
        for (auto fact : Instance().mFacts)
        {
            // !!! test runner should be single function
            // to avoid duplicated code
            try
            {
                std::cout << "fact " << facts++ << " of " << Instance().mFacts.size() << std::endl;
                fact();
            }
            catch (xUnitAssert &)
            {
                std::cout << "Caught xUnitAssert." << std::endl;
            }
        }

        // !!! randomize
        for (auto theorySet : Instance().mTheories)
        {
            std::cout << "theory " << theories++ << " of " << Instance().mTheories.size() << std::endl;

            auto instance = 1;

            for (auto theory : theorySet)
            {
                try
                {
                    std::cout << "theory instance " << instance++ << " of " << theorySet.size() << std::endl;
                    theory();
                }
                catch (xUnitAssert &)
                {
                    std::cout << "Caught xUnitAssert." << std::endl;
                }
            }
        }
    }

private:
    static xUnit &Instance()
    {
        static xUnit instance;
        return instance;
    }

    std::vector<std::function<void()>> mFacts;
    std::vector<std::vector<std::function<void()>>> mTheories;
};

#define FACT(fn) \
    void fn(); \
    namespace { namespace fn ## _ns { xUnit::Register reg(&fn); } } \
    void fn()

FACT(FactOk)
{
    Assert.Equal(1, 1);
}

FACT(FactFails)
{
    Assert.Equal(0, 1);
}

#define THEORY_DATA(theory, ...) \
    void theory(__VA_ARGS__); \
    std::vector<std::tuple<__VA_ARGS__>> theory ## _data(); \
    namespace { namespace theory ## _ns { xUnit::Register reg(&theory, &theory ## _data); } } \
    std::vector<std::tuple<__VA_ARGS__>> theory ## _data()

//void TheoryWorks(int, char, bool);
//std::vector<std::tuple<int, char, bool>> DataGen();
//namespace { namespace TheoryWorks_ns { xUnit::Register reg(&TheoryWorks, &DataGen); } }
//

void Theory(int x, char y, bool equal)
{
    if (equal)
    {
        Assert.Equal(x, y);
    }
    else
    {
        Assert.NotEqual(x, y);
    }
}

THEORY_DATA(Theory, int, char, bool)
//std::vector<std::tuple<int, char, bool>> DataGen()
{
    auto result = std::vector<std::tuple<int, char, bool>>();
    result.push_back(std::make_tuple(1, (char)1, true));
    result.push_back(std::make_tuple(0, (char)1, false));
    result.push_back(std::make_tuple(0, (char)1, true));
    return result;
}

int main()
{
    xUnit::RunAllTests();
}
<|endoftext|>


<commit_before>#include "flutterDemo.h"

#include <nds/arm9/video.h>
#include <nds/dma.h>

extern uint16_t objTileData[8 * 8 / 4];
extern _palette bgPalette;
extern _palette objPalette;

FlutterDemo::FlutterDemo() {}
FlutterDemo::~FlutterDemo() {}

void FlutterDemo::Load() {
	BaseParticleDemo::Load();

	setupParticles();
	loadGraphics();
}

void FlutterDemo::Unload() {
	BaseParticleDemo::Unload();
}

void FlutterDemo::PrepareFrame(VramBatcher &) {
	buildObjectsFromParticles();
}

void FlutterDemo::AcceptInput() {}

void FlutterDemo::setupParticles() {
	for(int y = 0; y < SCREEN_HEIGHT; y += 10) {
		for(int x = 0; x < SCREEN_WIDTH; x += 10) {
			particles.push_back(std::move(
				Particle(x, y, 0)
			));
		}
	}
}

void FlutterDemo::loadGraphics() {

	vramSetBankA(VRAM_A_MAIN_SPRITE);

	//load pixel data
	dmaCopyWords(3, objTileData, SPRITE_GFX,sizeof(objTileData));

	//setup palettes
	dmaCopyWords(3, bgPalette, BG_PALETTE, sizeof(bgPalette));
	dmaCopyWords(3, objPalette, SPRITE_PALETTE, sizeof(bgPalette));
}

uint16_t objTileData[8 * 8 / 4] = {
	1,0
};

_palette bgPalette = {RGB8(0,0,0)};
_palette objPalette = {RGB8(255,0,255),RGB8(255,255,255),
RGB8(255,0,0),RGB8(0,255,0),RGB8(0,0,255),
RGB8(255,255,0),RGB8(255,0,255),RGB8(0,255,255),
RGB8(0,0,0)};<commit_msg>Corrrect palette for palette swapping<commit_after>#include "flutterDemo.h"

#include <nds/arm9/video.h>
#include <nds/dma.h>

extern uint16_t objTileData[8 * 8 / 4];
extern _palette bgPalette;
extern _palette objPalette;

FlutterDemo::FlutterDemo() {}
FlutterDemo::~FlutterDemo() {}

void FlutterDemo::Load() {
	BaseParticleDemo::Load();

	setupParticles();
	loadGraphics();
}

void FlutterDemo::Unload() {
	BaseParticleDemo::Unload();
}

void FlutterDemo::PrepareFrame(VramBatcher &) {
	buildObjectsFromParticles();
}

void FlutterDemo::AcceptInput() {}

void FlutterDemo::setupParticles() {
	for(int y = 0; y < SCREEN_HEIGHT; y += 10) {
		for(int x = 0; x < SCREEN_WIDTH; x += 10) {
			particles.push_back(std::move(
				Particle(x, y, 0, x%4)
			));
		}
	}
}

void FlutterDemo::loadGraphics() {

	vramSetBankA(VRAM_A_MAIN_SPRITE);

	//load pixel data
	dmaCopyWords(3, objTileData, SPRITE_GFX,sizeof(objTileData));

	//setup palettes
	dmaCopyWords(3, bgPalette, BG_PALETTE, sizeof(bgPalette));
	dmaCopyWords(3, objPalette, SPRITE_PALETTE, sizeof(bgPalette));
}

uint16_t objTileData[8 * 8 / 4] = {
	1,0
};

_palette bgPalette = {RGB8(0,0,0)};
_palette objPalette = {
	RGB8(255,0,255),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(255,0,255),RGB8(255,255,255),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(255,0,255),RGB8(255,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(255,0,255),RGB8(0,255,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(255,0,255),RGB8(0,0,255),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(255,0,255),RGB8(255,255,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(255,0,255),RGB8(255,0,255),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(255,0,255),RGB8(0,255,255),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
	RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),RGB8(0,0,0),
RGB8(0,0,0)};<|endoftext|>


<commit_before>/*************************************************************************************
 *  Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@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 "device.h"
#include "upower_interface.h"

Device::Device(QObject* parent)
 : QObject(parent)
 , m_isReady(false)
 , m_isLaptop(false)
 , m_isLidClosed(false)
 , m_isDocked(false)
{
    m_freedesktop = new OrgFreedesktopDBusPropertiesInterface("org.freedesktop.UPower",
                                                              "/org/freedesktop/UPower",
                                                              QDBusConnection::systemBus());

    m_upower = new OrgFreedesktopUPowerInterface("org.freedesktop.UPower",
                                                 "/org/freedesktop/UPower",
                                                 QDBusConnection::systemBus());

    connect(m_upower, SIGNAL(Changed()), SLOT(changed()));
    QMetaObject::invokeMethod(this, "init", Qt::QueuedConnection);
}

Device::~Device()
{
    delete m_upower;
    delete m_freedesktop;
}

void Device::init()
{
    fetchIsLaptop();
}

void Device::changed()
{
    fetchLidIsClosed();
}

void Device::setReady()
{
    m_isReady = true;
    Q_EMIT ready();
}

bool Device::isReady()
{
    return m_isReady;
}

bool Device::isLaptop()
{
    return m_isLaptop;
}

bool Device::isLidClosed()
{
    return m_isLidClosed;
}

bool Device::isDocked()
{
    return m_isDocked;
}

void Device::fetchIsLaptop()
{
    QDBusPendingReply<QVariant> res = m_freedesktop->Get("org.freedesktop.UPower", "LidIsPresent");
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(res);
    connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(isLaptopFetched(QDBusPendingCallWatcher*)));
}

void Device::isLaptopFetched(QDBusPendingCallWatcher* watcher)
{
    const QDBusPendingReply<QVariant> reply = *watcher;
    if (reply.isError()) {
        qDebug() << "Couldn't get if the device is a laptop: " << reply.error().message();
        return;
    }

    m_isLaptop = reply.value().toBool();
    watcher->deleteLater();

    if (!m_isLaptop) {
        setReady();
        return;
    }

    fetchLidIsClosed();
}

void Device::fetchLidIsClosed()
{
    QDBusPendingReply<QVariant> res = m_freedesktop->Get("org.freedesktop.UPower", "LidIsClosed");
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(res);
    connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(isLaptopFetched(QDBusPendingCallWatcher*)));
}

void Device::isLidClosedFetched(QDBusPendingCallWatcher* watcher)
{
    const QDBusPendingReply<QVariant> reply = *watcher;
    if (reply.isError()) {
        qDebug() << "Couldn't get if the device is a laptop: " << reply.error().message();
        return;
    }

    bool oldValue = m_isLidClosed;;
    m_isLidClosed = reply.value().toBool();
    watcher->deleteLater();

    if (m_isReady && (oldValue != m_isLidClosed)) {
        Q_EMIT lidIsClosedChanged(m_isLidClosed, oldValue);
    }

    fetchIsDocked();
}

void Device::fetchIsDocked()
{
    setReady();
}<commit_msg>Connect to the right slot (Damn auto completation !)<commit_after>/*************************************************************************************
 *  Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@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 "device.h"
#include "upower_interface.h"

Device::Device(QObject* parent)
 : QObject(parent)
 , m_isReady(false)
 , m_isLaptop(false)
 , m_isLidClosed(false)
 , m_isDocked(false)
{
    m_freedesktop = new OrgFreedesktopDBusPropertiesInterface("org.freedesktop.UPower",
                                                              "/org/freedesktop/UPower",
                                                              QDBusConnection::systemBus());

    m_upower = new OrgFreedesktopUPowerInterface("org.freedesktop.UPower",
                                                 "/org/freedesktop/UPower",
                                                 QDBusConnection::systemBus());

    connect(m_upower, SIGNAL(Changed()), SLOT(changed()));
    QMetaObject::invokeMethod(this, "init", Qt::QueuedConnection);
}

Device::~Device()
{
    delete m_upower;
    delete m_freedesktop;
}

void Device::init()
{
    fetchIsLaptop();
}

void Device::changed()
{
    fetchLidIsClosed();
}

void Device::setReady()
{
    m_isReady = true;
    Q_EMIT ready();
}

bool Device::isReady()
{
    return m_isReady;
}

bool Device::isLaptop()
{
    return m_isLaptop;
}

bool Device::isLidClosed()
{
    return m_isLidClosed;
}

bool Device::isDocked()
{
    return m_isDocked;
}

void Device::fetchIsLaptop()
{
    QDBusPendingReply<QVariant> res = m_freedesktop->Get("org.freedesktop.UPower", "LidIsPresent");
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(res);
    connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(isLaptopFetched(QDBusPendingCallWatcher*)));
}

void Device::isLaptopFetched(QDBusPendingCallWatcher* watcher)
{
    const QDBusPendingReply<QVariant> reply = *watcher;
    if (reply.isError()) {
        qDebug() << "Couldn't get if the device is a laptop: " << reply.error().message();
        return;
    }

    m_isLaptop = reply.value().toBool();
    watcher->deleteLater();

    if (!m_isLaptop) {
        setReady();
        return;
    }

    fetchLidIsClosed();
}

void Device::fetchLidIsClosed()
{
    QDBusPendingReply<QVariant> res = m_freedesktop->Get("org.freedesktop.UPower", "LidIsClosed");
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(res);
    connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(isLidClosedFetched(QDBusPendingCallWatcher*)));
}

void Device::isLidClosedFetched(QDBusPendingCallWatcher* watcher)
{
    const QDBusPendingReply<QVariant> reply = *watcher;
    if (reply.isError()) {
        qDebug() << "Couldn't get if the device is a laptop: " << reply.error().message();
        return;
    }

    bool oldValue = m_isLidClosed;;
    m_isLidClosed = reply.value().toBool();
    watcher->deleteLater();

    if (m_isReady && (oldValue != m_isLidClosed)) {
        Q_EMIT lidIsClosedChanged(m_isLidClosed, oldValue);
    }

    fetchIsDocked();
}

void Device::fetchIsDocked()
{
    setReady();
}<|endoftext|>


<commit_before>#include "ProcessHelper.hpp"

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>

using namespace et;

void ProcessHelper::daemonize() {
  pid_t pid;

  /* Fork off the parent process */
  pid = fork();

  /* An error occurred */
  if (pid < 0)
    exit(EXIT_FAILURE);

  /* Success: Let the parent terminate */
  if (pid > 0)
    exit(EXIT_SUCCESS);

  /* On success: The child process becomes session leader */
  if (setsid() < 0)
    exit(EXIT_FAILURE);

  /* Catch, ignore and handle signals */
  //TODO: Implement a working signal handler */
  signal(SIGCHLD, SIG_IGN);
  signal(SIGHUP, SIG_IGN);

  /* Fork off for the second time*/
  pid = fork();

  /* An error occurred */
  if (pid < 0)
    exit(EXIT_FAILURE);

  /* Success: Let the parent terminate */
  if (pid > 0)
    exit(EXIT_SUCCESS);

  /* Set new file permissions */
  //umask(0);

  /* Close all open file descriptors */
  int x;
  for (x = sysconf(_SC_OPEN_MAX); x>0; x--)
  {
    close (x);
  }

  /* Reopen stdin (fd = 0), stdout (fd = 1), stderr (fd = 2) */
  stdin = fopen("/dev/null", "r");
  stdout = fopen("/tmp/et_err", "w+");
  setvbuf(stdout, NULL, _IOLBF, BUFSIZ);  // set to line buffering
  stderr = fopen("/tmp/et_err", "w+");
  setvbuf(stderr, NULL, _IOLBF, BUFSIZ);  // set to line buffering

  /* Open the log file */
  //openlog ("ETServer", LOG_PID, LOG_DAEMON);
}
<commit_msg>add signal.h<commit_after>#include "ProcessHelper.hpp"

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
#include <signal.h>

using namespace et;

void ProcessHelper::daemonize() {
  pid_t pid;

  /* Fork off the parent process */
  pid = fork();

  /* An error occurred */
  if (pid < 0)
    exit(EXIT_FAILURE);

  /* Success: Let the parent terminate */
  if (pid > 0)
    exit(EXIT_SUCCESS);

  /* On success: The child process becomes session leader */
  if (setsid() < 0)
    exit(EXIT_FAILURE);

  /* Catch, ignore and handle signals */
  //TODO: Implement a working signal handler */
  signal(SIGCHLD, SIG_IGN);
  signal(SIGHUP, SIG_IGN);

  /* Fork off for the second time*/
  pid = fork();

  /* An error occurred */
  if (pid < 0)
    exit(EXIT_FAILURE);

  /* Success: Let the parent terminate */
  if (pid > 0)
    exit(EXIT_SUCCESS);

  /* Set new file permissions */
  //umask(0);

  /* Close all open file descriptors */
  int x;
  for (x = sysconf(_SC_OPEN_MAX); x>0; x--)
  {
    close (x);
  }

  /* Reopen stdin (fd = 0), stdout (fd = 1), stderr (fd = 2) */
  stdin = fopen("/dev/null", "r");
  stdout = fopen("/tmp/et_err", "w+");
  setvbuf(stdout, NULL, _IOLBF, BUFSIZ);  // set to line buffering
  stderr = fopen("/tmp/et_err", "w+");
  setvbuf(stderr, NULL, _IOLBF, BUFSIZ);  // set to line buffering

  /* Open the log file */
  //openlog ("ETServer", LOG_PID, LOG_DAEMON);
}
<|endoftext|>