<commit_before>/*
 * HTTP/1.0 for streams sockets - implementation
 * Copyright(c) 2003-2004 of wave++ (Yuri D'Elia)
 * Distributed under GNU LGPL without ANY warranty.
 */

// interface
#include "http.hh"

// local headers
#include "resolver.hh"
#include "urlencode.hh"

// system headers
#include <stdexcept>
#include <memory>
#include <string>
using std::string;
using std::getline;

#include <sstream>
using std::istringstream;

// c system headers
#include <netdb.h>
#include <string.h>

// implementation
namespace Http
{
  Http::Http(const char* host, const int port)
  {
    this->host = strdup(host);
    this->port = port? port: getSrvPort();
    addr = resolve(host);
  }

  Http::~Http()
  {
    delete []host;
  }

  int
  Http::getSrvPort()
  {
    servent* se(getservbyname(Proto::proto, Proto::protoTy));
    if(!se)
      throw
        std::runtime_error("error while trying to identify http port number");

    return se->s_port;
  }

  void
  Http::readReply(Socket& s, Reply& reply)
  {
    char proto[Proto::hdrLen];
    *proto = 0;

    char buf[Proto::hdrLen];
    size_t answLen;

    // read all lines
    while((answLen = s.gets(buf, Proto::hdrLen)) > Proto::endlSz)
    {
      if(reply.headers || !*proto)
      {
        // cut tailing newlines from the buffer
        while(strchr(Proto::endl, buf[answLen - 1]))
          buf[--answLen] = 0;

	if(!*proto)
	  memcpy(proto, buf, answLen);
	else if(reply.headers)
	  reply.headers->push_back(string(buf, answLen));
      }
    }

    // parse the first protocol line
    istringstream in(proto);
    in >> reply.proto;
    in >> reply.code;
    in >> std::ws;
    getline(in, reply.description);
  }

  Socket*
  Http::gen(const char* act, const char* path,
      Reply& reply, const Header* headers)
  {
    using std::auto_ptr;
    using std::string;

    auto_ptr<Socket> s(new Socket(addr, port));

    // request
    string req;
    req = string(act) + " " + urlEncode(path) + " " +
      Proto::version + Proto::endl;
    s->write(req.c_str(), req.size());

    // host name
    req = string("Host: ") + host + Proto::endl;
    s->write(req.c_str(), req.size());

    // headers
    if(headers)
      for(Header::const_iterator it = headers->begin();
          it != headers->end(); ++it)
      {
        s->write(it->c_str(), it->size());
        s->write(Proto::endl, Proto::endlSz);
      }

    // final newline
    s->write(Proto::endl, Proto::endlSz);

    // fetch the answer headers
    readReply(*s, reply);

    return s.release();
  }

  Socket*
  Http::get(const char* file, Reply& reply, const Header* headers)
  {
    using std::auto_ptr;
    auto_ptr<Socket> s(gen(Proto::get, file, reply, headers));

    // close the write end
    s->close(SHUT_WR);

    return s.release();
  }
}
<commit_msg>Reduce request fragmentation.<commit_after>/*
 * HTTP/1.0 for streams sockets - implementation
 * Copyright(c) 2003-2004 of wave++ (Yuri D'Elia)
 * Distributed under GNU LGPL without ANY warranty.
 */

// interface
#include "http.hh"

// local headers
#include "resolver.hh"
#include "urlencode.hh"

// system headers
#include <stdexcept>
#include <memory>
#include <string>
using std::string;
using std::getline;

#include <sstream>
using std::istringstream;

// c system headers
#include <netdb.h>
#include <string.h>

// implementation
namespace Http
{
  Http::Http(const char* host, const int port)
  {
    this->host = strdup(host);
    this->port = port? port: getSrvPort();
    addr = resolve(host);
  }

  Http::~Http()
  {
    delete []host;
  }

  int
  Http::getSrvPort()
  {
    servent* se(getservbyname(Proto::proto, Proto::protoTy));
    if(!se)
      throw
        std::runtime_error("error while trying to identify http port number");

    return se->s_port;
  }

  void
  Http::readReply(Socket& s, Reply& reply)
  {
    char proto[Proto::hdrLen];
    *proto = 0;

    char buf[Proto::hdrLen];
    size_t answLen;

    // read all lines
    while((answLen = s.gets(buf, Proto::hdrLen)) > Proto::endlSz)
    {
      if(reply.headers || !*proto)
      {
        // cut tailing newlines from the buffer
        while(strchr(Proto::endl, buf[answLen - 1]))
          buf[--answLen] = 0;

	if(!*proto)
	  memcpy(proto, buf, answLen);
	else if(reply.headers)
	  reply.headers->push_back(string(buf, answLen));
      }
    }

    // parse the first protocol line
    istringstream in(proto);
    in >> reply.proto;
    in >> reply.code;
    in >> std::ws;
    getline(in, reply.description);
  }

  Socket*
  Http::gen(const char* act, const char* path,
      Reply& reply, const Header* headers)
  {
    using std::auto_ptr;
    using std::string;

    auto_ptr<Socket> s(new Socket(addr, port));

    // request
    string req;
    req = string(act) + " " + urlEncode(path) + " " +
      Proto::version + Proto::endl;
    req += string("Host: ") + host + Proto::endl;

    // headers
    if(headers)
      for(Header::const_iterator it = headers->begin();
          it != headers->end(); ++it)
	req += *it + Proto::endl;

    // final newline
    req += Proto::endl;
    s->write(req.c_str(), req.size());

    // fetch the answer headers
    readReply(*s, reply);

    return s.release();
  }

  Socket*
  Http::get(const char* file, Reply& reply, const Header* headers)
  {
    using std::auto_ptr;
    auto_ptr<Socket> s(gen(Proto::get, file, reply, headers));

    // close the write end
    s->close(SHUT_WR);

    return s.release();
  }
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#if !defined(GCCDEFINITIONS_HEADER_GUARD_1357924680)
#define GCCDEFINITIONS_HEADER_GUARD_1357924680

// ---------------------------------------------------------------------------
//  A define in the build for each project is also used to control whether
//  the export keyword is from the project's viewpoint or the client's.
//  These defines provide the platform specific keywords that they need
//  to do this.
// ---------------------------------------------------------------------------
#define XALAN_PLATFORM_EXPORT
#define XALAN_PLATFORM_IMPORT
#define XALAN_PLATFORM_EXPORT_FUNCTION(T) T XALAN_PLATFORM_EXPORT
#define XALAN_PLATFORM_IMPORT_FUNCTION(T) T XALAN_PLATFORM_IMPORT

#define XALAN_NO_MEMBER_TEMPLATES
#define XALAN_RTTI_AVAILABLE
#define XALAN_OLD_STREAM_HEADERS
#define XALAN_SGI_BASED_STL
#define XALAN_XALANDOMCHAR_USHORT_MISMATCH
#define XALAN_NO_STD_ALLOCATORS
#define XALAN_POSIX2_AVAILABLE

// This will change, depending upon the target platform.
#if defined(__BIG_ENDIAN__)
#define XALAN_BIG_ENDIAN
#elif defined(__LITTLE_ENDIAN__)
#define XALAN_LITTLE_ENDIAN
#else
#error XALAN_BIG_ENDIAN or XALAN_LITTLE_ENDIAN must be defined for this platform!
#endif

#define XALAN_UNALIGNED

#endif	// GCCDEFINITIONS_HEADER_GUARD_1357924680
<commit_msg>Fixed endian-ness defines.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#if !defined(GCCDEFINITIONS_HEADER_GUARD_1357924680)
#define GCCDEFINITIONS_HEADER_GUARD_1357924680

// ---------------------------------------------------------------------------
//  A define in the build for each project is also used to control whether
//  the export keyword is from the project's viewpoint or the client's.
//  These defines provide the platform specific keywords that they need
//  to do this.
// ---------------------------------------------------------------------------
#define XALAN_PLATFORM_EXPORT
#define XALAN_PLATFORM_IMPORT
#define XALAN_PLATFORM_EXPORT_FUNCTION(T) T XALAN_PLATFORM_EXPORT
#define XALAN_PLATFORM_IMPORT_FUNCTION(T) T XALAN_PLATFORM_IMPORT

#define XALAN_NO_MEMBER_TEMPLATES
#define XALAN_RTTI_AVAILABLE
#define XALAN_OLD_STREAM_HEADERS
#define XALAN_SGI_BASED_STL
#define XALAN_XALANDOMCHAR_USHORT_MISMATCH
#define XALAN_NO_STD_ALLOCATORS
#define XALAN_POSIX2_AVAILABLE

// This will change, depending upon the target platform.
#if defined(__BIG_ENDIAN__)
#define XALAN_BIG_ENDIAN
#elif defined(__LITTLE_ENDIAN__)
#define XALAN_LITTLE_ENDIAN
#elif defined(SOLARIS) || defined(powerpc) || defined(__sparc__) || defined(AIX)
#define XALAN_BIG_ENDIAN
#elif defined(__i386__) || defined(__alpha__)
#define XALAN_LITLE_ENDIAN
#else
#error XALAN_BIG_ENDIAN or XALAN_LITTLE_ENDIAN must be defined for this platform!
#endif

#define XALAN_UNALIGNED

#endif	// GCCDEFINITIONS_HEADER_GUARD_1357924680
<|endoftext|>


<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 "Constituent.h"

#include <chrono>
#include <iomanip>
#include <thread>

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

#include "Agency/Agent.h"
#include "Aql/Query.h"
#include "Aql/QueryRegistry.h"
#include "Basics/ConditionLocker.h"
#include "Cluster/ClusterComm.h"
#include "Logger/Logger.h"
#include "Random/RandomGenerator.h"
#include "Utils/OperationOptions.h"
#include "Utils/OperationResult.h"
#include "Utils/SingleCollectionTransaction.h"
#include "Utils/StandaloneTransactionContext.h"
#include "VocBase/collection.h"
#include "VocBase/vocbase.h"
#include "Agency/NotifierThread.h"

using namespace arangodb::consensus;
using namespace arangodb::rest;
using namespace arangodb::velocypack;
using namespace arangodb;

/// Raft role names for display purposes
const std::vector<std::string> roleStr ({"Follower", "Candidate", "Leader"});

/// Configure with agent's configuration
void Constituent::configure(Agent* agent) {

  _agent = agent;
  TRI_ASSERT(_agent != nullptr);

  if (size() == 1) {
    _role = LEADER;
  } else {
    _id = _agent->config().id;
    if (_agent->config().notify) {  // (notify everyone)
      notifyAll();
    }
  }

}

// Default ctor
Constituent::Constituent()
  : Thread("Constituent"),
    _vocbase(nullptr),
    _queryRegistry(nullptr),
    _term(0),
    _cast(false),
    _leaderID((std::numeric_limits<arangodb::consensus::id_t>::max)()),
    _id(0),
    _role(FOLLOWER),
    _agent(nullptr),
    _votedFor((std::numeric_limits<arangodb::consensus::id_t>::max)()),
    _notifier(nullptr) {}

/// Shutdown if not already
Constituent::~Constituent() {
  shutdown();
}

/// Configuration
config_t const& Constituent::config() const {
  return _agent->config();
}

/// Wait for sync
bool Constituent::waitForSync() const {
  return _agent->config().waitForSync;
}

/// Random sleep times in election process
duration_t Constituent::sleepFor(double min_t, double max_t) {
  int32_t left = 1000*min_t, right = 1000*max_t;
  return duration_t(
    static_cast<long>(RandomGenerator::interval(left, right)));
}

/// Get my term
term_t Constituent::term() const {
  MUTEX_LOCKER(guard, _castLock);
  return _term;
}

/// Update my term
void Constituent::term(term_t t) {

  term_t tmp;
  {
    MUTEX_LOCKER(guard, _castLock);
    tmp = _term;
    _term = t;
  }

  if (tmp != t) {

    LOG_TOPIC(DEBUG, Logger::AGENCY)
      << _id << ": " << roleStr[_role] << " term " << t;

    Builder body;
    body.add(VPackValue(VPackValueType::Object));
    std::ostringstream i_str;
    i_str << std::setw(20) << std::setfill('0') << t;
    body.add("_key", Value(i_str.str()));
    body.add("term", Value(t));
    body.add("voted_for", Value((uint32_t)_votedFor));
    body.close();

    TRI_ASSERT(_vocbase != nullptr);
    auto transactionContext =
        std::make_shared<StandaloneTransactionContext>(_vocbase);
    SingleCollectionTransaction trx(transactionContext, "election",
                                    TRI_TRANSACTION_WRITE);

    int res = trx.begin();

    if (res != TRI_ERROR_NO_ERROR) {
      THROW_ARANGO_EXCEPTION(res);
    }

    OperationOptions options;
    options.waitForSync = false;
    options.silent = true;

    OperationResult result = trx.insert("election", body.slice(), options);
    trx.finish(result.code);

  }

}

/// My role
role_t Constituent::role() const {
  MUTEX_LOCKER(guard, _castLock);
  return _role;
}

/// Become follower in term
void Constituent::follow(term_t t) {

  MUTEX_LOCKER(guard, _castLock);

  if (_role != FOLLOWER) {
    LOG_TOPIC(DEBUG, Logger::AGENCY)
      << _id << ": Converting to follower in term " << t;
  }

  _term = t;
  _role = FOLLOWER;

}

/// Become leader
void Constituent::lead(std::vector<bool> const& votes) {

  {
    MUTEX_LOCKER(guard, _castLock);

    if (_role == LEADER) {
      return;
    }

    _role     = LEADER;
    _leaderID = _id;
  }

  std::stringstream ss;
  ss << _id << ": Converted to leader in term " << _term << " with votes (";
  for (auto const& vote : votes) {
    ss << vote;
  }
  ss << ")";

  LOG_TOPIC(DEBUG, Logger::AGENCY) << ss.str();
  _agent->lead();  // We need to rebuild spear_head and read_db;

}

/// Become follower
void Constituent::candidate() {

  MUTEX_LOCKER(guard, _castLock);

  if (_role != CANDIDATE)
    LOG_TOPIC(DEBUG, Logger::AGENCY)
        << _id << ": Converted to candidate in term " << _term;

  _role = CANDIDATE;

}

/// Leading?
bool Constituent::leading() const {
  MUTEX_LOCKER(guard, _castLock);
  return _role == LEADER;
}

/// Following?
bool Constituent::following() const {
  MUTEX_LOCKER(guard, _castLock);
  return _role == FOLLOWER;
}

/// Runnig as candidate?
bool Constituent::running() const {
  MUTEX_LOCKER(guard, _castLock);
  return _role == CANDIDATE;
}

/// Get current leader's id
arangodb::consensus::id_t Constituent::leaderID() const {
  return _leaderID;
}

/// Agency size
size_t Constituent::size() const {
  return config().size();
}

/// Get endpoint to an id
std::string const& Constituent::endpoint(arangodb::consensus::id_t id) const {
  return config().endpoints[id];
}

/// Get all endpoints
std::vector<std::string> const& Constituent::endpoints() const {
  return config().endpoints;
}

/// Notify peers of updated endpoints
void Constituent::notifyAll() {

  // Send request to all but myself
  std::vector<std::string> toNotify;
  for (arangodb::consensus::id_t i = 0; i < size(); ++i) {
    if (i != _id) {
      toNotify.push_back(endpoint(i));
    }
  }

  // Body contains endpoints list
  auto body = std::make_shared<VPackBuilder>();
  body->openObject();
  body->add("endpoints", VPackValue(VPackValueType::Array));

  for (auto const& i : endpoints()) {
    body->add(Value(i));
  }

  body->close();
  body->close();

  // Last process notifies everyone
  std::stringstream path;

  path << "/_api/agency_priv/notifyAll?term=" << _term << "&agencyId=" << _id;

  _notifier = std::make_unique<NotifierThread>(path.str(), body, toNotify);
  _notifier->start();

}

/// @brief Vote
bool Constituent::vote(term_t term, arangodb::consensus::id_t id,
                       index_t prevLogIndex, term_t prevLogTerm) {

  term_t t = 0;
  arangodb::consensus::id_t lid = 0;
  bool cast = false;

  {
    MUTEX_LOCKER(guard, _castLock);
    t = _term;
    lid = _leaderID;
    cast = _cast;
    _cast = true;
  }

  if (term > t || (t == term && lid == id && !cast)) {
    this->term(term);
    {
      MUTEX_LOCKER(guard, _castLock);
      _votedFor = id;  // The guy I voted for I assume leader.
      _leaderID = id;
    }
    if (_role > FOLLOWER) {
      follow(_term);
    }
    {
      CONDITION_LOCKER(guard, _cv);
      _cv.signal();
    }
    return true;
  }

  return false;

}

/// @brief Call to election
void Constituent::callElection() {
  std::vector<bool> votes(size(), false);

  votes.at(_id) = true;  // vote for myself
  _cast = true;
  if (_role == CANDIDATE) {
    this->term(_term + 1);  // raise my term
  }

  std::string body;
  std::vector<OperationID> operationIDs(config().endpoints.size());
  std::stringstream path;

  path << "/_api/agency_priv/requestVote?term=" << _term
       << "&candidateId=" << _id << "&prevLogIndex=" << _agent->lastLog().index
       << "&prevLogTerm=" << _agent->lastLog().term;

  // Ask everyone for their vote
  for (arangodb::consensus::id_t i = 0; i < config().endpoints.size(); ++i) {
    if (i != _id && endpoint(i) != "") {
      auto headerFields =
          std::make_unique<std::unordered_map<std::string, std::string>>();
      operationIDs[i] = arangodb::ClusterComm::instance()->asyncRequest(
          "1", 1, config().endpoints[i], GeneralRequest::RequestType::GET,
          path.str(), std::make_shared<std::string>(body), headerFields,
          nullptr, config().minPing, true);
    }
  }

  // Wait randomized timeout
  std::this_thread::sleep_for(
      sleepFor(.5 * config().minPing, .8 * config().minPing));

  // Collect votes
  // FIXME: This code can be improved: One can wait for an arbitrary
  // result by creating a coordinatorID and waiting for a pattern.
  for (arangodb::consensus::id_t i = 0; i < config().endpoints.size(); ++i) {
    if (i != _id && endpoint(i) != "") {
      ClusterCommResult res =
          arangodb::ClusterComm::instance()->enquire(operationIDs[i]);

      if (res.status == CL_COMM_SENT) {  // Request successfully sent
        res = arangodb::ClusterComm::instance()->wait(
            "1", 1, operationIDs[i], "1");
        std::shared_ptr<Builder> body = res.result->getBodyVelocyPack();
        if (body->isEmpty()) {  // body empty
          continue;
        } else {
          if (body->slice().isObject()) {  // body
            VPackSlice slc = body->slice();
            if (slc.hasKey("term") && slc.hasKey("voteGranted")) {  // OK
              term_t t = slc.get("term").getUInt();
              if (t > _term) {  // follow?
                follow(t);
                break;
              }
              votes[i] = slc.get("voteGranted").getBool();  // Get vote
            }
          }
        }
      } else {  // Request failed
        votes[i] = false;
      }
    }
  }

  // Count votes
  size_t yea = 0;
  for (size_t i = 0; i < size(); ++i) {
    if (votes[i]) {
      yea++;
    }
  }

  // Evaluate election results
  if (yea > size() / 2) {
    lead(votes);
  } else {
    follow(_term);
  }

}

/// Start clean shutdown
void Constituent::beginShutdown() {

  _notifier.reset();
  Thread::beginShutdown();

  CONDITION_LOCKER(guard, _cv);
  guard.broadcast();

}

/// Start operation
bool Constituent::start(TRI_vocbase_t* vocbase,
                        aql::QueryRegistry* queryRegistry) {

  _vocbase = vocbase;
  _queryRegistry = queryRegistry;

  return Thread::start();

}

/// Get persisted information and run election process
void Constituent::run() {

  TRI_ASSERT(_vocbase != nullptr);
  auto bindVars = std::make_shared<VPackBuilder>();
  bindVars->openObject();
  bindVars->close();

  // Most recent vote
  std::string const aql("FOR l IN election SORT l._key DESC LIMIT 1 RETURN l");
  arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), bindVars,
                             nullptr, arangodb::aql::PART_MAIN);

  auto queryResult = query.execute(_queryRegistry);
  if (queryResult.code != TRI_ERROR_NO_ERROR) {
    THROW_ARANGO_EXCEPTION_MESSAGE(queryResult.code, queryResult.details);
  }

  VPackSlice result = queryResult.result->slice();

  if (result.isArray()) {
    for (auto const& i : VPackArrayIterator(result)) {
      try {
        _term = i.get("term").getUInt();
        _votedFor =
            static_cast<decltype(_votedFor)>(i.get("voted_for").getUInt());
      } catch (std::exception const&) {
        LOG_TOPIC(ERR, Logger::AGENCY)
            << "Persisted election entries corrupt! Defaulting term,vote (0,0)";
      }
    }
  }

  // Always start off as follower
  while (!this->isStopping() && size() > 1) {

    if (_role == FOLLOWER) {
      bool cast = false;

      {
        MUTEX_LOCKER(guard, _castLock);
        _cast = false;  // New round set not cast vote
      }

      int32_t left = 1000000*config().minPing, right = 1000000*config().maxPing;
      long rand_wait = static_cast<long>(RandomGenerator::interval(left, right));

      {
        CONDITION_LOCKER(guardv, _cv);
        _cv.wait(rand_wait);
      }

      {
        MUTEX_LOCKER(guard, _castLock);
        cast = _cast;
      }

      if (!cast) {
        candidate();  // Next round, we are running
      }

    } else {
      callElection();  // Run for office
    }

  }

}
<commit_msg>fix VS warnings<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 "Constituent.h"

#include <chrono>
#include <iomanip>
#include <thread>

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

#include "Agency/Agent.h"
#include "Aql/Query.h"
#include "Aql/QueryRegistry.h"
#include "Basics/ConditionLocker.h"
#include "Cluster/ClusterComm.h"
#include "Logger/Logger.h"
#include "Random/RandomGenerator.h"
#include "Utils/OperationOptions.h"
#include "Utils/OperationResult.h"
#include "Utils/SingleCollectionTransaction.h"
#include "Utils/StandaloneTransactionContext.h"
#include "VocBase/collection.h"
#include "VocBase/vocbase.h"
#include "Agency/NotifierThread.h"

using namespace arangodb::consensus;
using namespace arangodb::rest;
using namespace arangodb::velocypack;
using namespace arangodb;

/// Raft role names for display purposes
const std::vector<std::string> roleStr ({"Follower", "Candidate", "Leader"});

/// Configure with agent's configuration
void Constituent::configure(Agent* agent) {

  _agent = agent;
  TRI_ASSERT(_agent != nullptr);

  if (size() == 1) {
    _role = LEADER;
  } else {
    _id = _agent->config().id;
    if (_agent->config().notify) {  // (notify everyone)
      notifyAll();
    }
  }

}

// Default ctor
Constituent::Constituent()
  : Thread("Constituent"),
    _vocbase(nullptr),
    _queryRegistry(nullptr),
    _term(0),
    _cast(false),
    _leaderID((std::numeric_limits<arangodb::consensus::id_t>::max)()),
    _id(0),
    _role(FOLLOWER),
    _agent(nullptr),
    _votedFor((std::numeric_limits<arangodb::consensus::id_t>::max)()),
    _notifier(nullptr) {}

/// Shutdown if not already
Constituent::~Constituent() {
  shutdown();
}

/// Configuration
config_t const& Constituent::config() const {
  return _agent->config();
}

/// Wait for sync
bool Constituent::waitForSync() const {
  return _agent->config().waitForSync;
}

/// Random sleep times in election process
duration_t Constituent::sleepFor(double min_t, double max_t) {
  int32_t left = static_cast<int32_t>(1000.0 * min_t), right = static_cast<int32_t>(1000.0 * max_t);
  return duration_t(
    static_cast<long>(RandomGenerator::interval(left, right)));
}

/// Get my term
term_t Constituent::term() const {
  MUTEX_LOCKER(guard, _castLock);
  return _term;
}

/// Update my term
void Constituent::term(term_t t) {

  term_t tmp;
  {
    MUTEX_LOCKER(guard, _castLock);
    tmp = _term;
    _term = t;
  }

  if (tmp != t) {

    LOG_TOPIC(DEBUG, Logger::AGENCY)
      << _id << ": " << roleStr[_role] << " term " << t;

    Builder body;
    body.add(VPackValue(VPackValueType::Object));
    std::ostringstream i_str;
    i_str << std::setw(20) << std::setfill('0') << t;
    body.add("_key", Value(i_str.str()));
    body.add("term", Value(t));
    body.add("voted_for", Value((uint32_t)_votedFor));
    body.close();

    TRI_ASSERT(_vocbase != nullptr);
    auto transactionContext =
        std::make_shared<StandaloneTransactionContext>(_vocbase);
    SingleCollectionTransaction trx(transactionContext, "election",
                                    TRI_TRANSACTION_WRITE);

    int res = trx.begin();

    if (res != TRI_ERROR_NO_ERROR) {
      THROW_ARANGO_EXCEPTION(res);
    }

    OperationOptions options;
    options.waitForSync = false;
    options.silent = true;

    OperationResult result = trx.insert("election", body.slice(), options);
    trx.finish(result.code);

  }

}

/// My role
role_t Constituent::role() const {
  MUTEX_LOCKER(guard, _castLock);
  return _role;
}

/// Become follower in term
void Constituent::follow(term_t t) {

  MUTEX_LOCKER(guard, _castLock);

  if (_role != FOLLOWER) {
    LOG_TOPIC(DEBUG, Logger::AGENCY)
      << _id << ": Converting to follower in term " << t;
  }

  _term = t;
  _role = FOLLOWER;

}

/// Become leader
void Constituent::lead(std::vector<bool> const& votes) {

  {
    MUTEX_LOCKER(guard, _castLock);

    if (_role == LEADER) {
      return;
    }

    _role     = LEADER;
    _leaderID = _id;
  }

  std::stringstream ss;
  ss << _id << ": Converted to leader in term " << _term << " with votes (";
  for (auto const& vote : votes) {
    ss << vote;
  }
  ss << ")";

  LOG_TOPIC(DEBUG, Logger::AGENCY) << ss.str();
  _agent->lead();  // We need to rebuild spear_head and read_db;

}

/// Become follower
void Constituent::candidate() {

  MUTEX_LOCKER(guard, _castLock);

  if (_role != CANDIDATE)
    LOG_TOPIC(DEBUG, Logger::AGENCY)
        << _id << ": Converted to candidate in term " << _term;

  _role = CANDIDATE;

}

/// Leading?
bool Constituent::leading() const {
  MUTEX_LOCKER(guard, _castLock);
  return _role == LEADER;
}

/// Following?
bool Constituent::following() const {
  MUTEX_LOCKER(guard, _castLock);
  return _role == FOLLOWER;
}

/// Runnig as candidate?
bool Constituent::running() const {
  MUTEX_LOCKER(guard, _castLock);
  return _role == CANDIDATE;
}

/// Get current leader's id
arangodb::consensus::id_t Constituent::leaderID() const {
  return _leaderID;
}

/// Agency size
size_t Constituent::size() const {
  return config().size();
}

/// Get endpoint to an id
std::string const& Constituent::endpoint(arangodb::consensus::id_t id) const {
  return config().endpoints[id];
}

/// Get all endpoints
std::vector<std::string> const& Constituent::endpoints() const {
  return config().endpoints;
}

/// Notify peers of updated endpoints
void Constituent::notifyAll() {

  // Send request to all but myself
  std::vector<std::string> toNotify;
  for (arangodb::consensus::id_t i = 0; i < size(); ++i) {
    if (i != _id) {
      toNotify.push_back(endpoint(i));
    }
  }

  // Body contains endpoints list
  auto body = std::make_shared<VPackBuilder>();
  body->openObject();
  body->add("endpoints", VPackValue(VPackValueType::Array));

  for (auto const& i : endpoints()) {
    body->add(Value(i));
  }

  body->close();
  body->close();

  // Last process notifies everyone
  std::stringstream path;

  path << "/_api/agency_priv/notifyAll?term=" << _term << "&agencyId=" << _id;

  _notifier = std::make_unique<NotifierThread>(path.str(), body, toNotify);
  _notifier->start();

}

/// @brief Vote
bool Constituent::vote(term_t term, arangodb::consensus::id_t id,
                       index_t prevLogIndex, term_t prevLogTerm) {

  term_t t = 0;
  arangodb::consensus::id_t lid = 0;
  bool cast = false;

  {
    MUTEX_LOCKER(guard, _castLock);
    t = _term;
    lid = _leaderID;
    cast = _cast;
    _cast = true;
  }

  if (term > t || (t == term && lid == id && !cast)) {
    this->term(term);
    {
      MUTEX_LOCKER(guard, _castLock);
      _votedFor = id;  // The guy I voted for I assume leader.
      _leaderID = id;
    }
    if (_role > FOLLOWER) {
      follow(_term);
    }
    {
      CONDITION_LOCKER(guard, _cv);
      _cv.signal();
    }
    return true;
  }

  return false;

}

/// @brief Call to election
void Constituent::callElection() {
  std::vector<bool> votes(size(), false);

  votes.at(_id) = true;  // vote for myself
  _cast = true;
  if (_role == CANDIDATE) {
    this->term(_term + 1);  // raise my term
  }

  std::string body;
  std::vector<OperationID> operationIDs(config().endpoints.size());
  std::stringstream path;

  path << "/_api/agency_priv/requestVote?term=" << _term
       << "&candidateId=" << _id << "&prevLogIndex=" << _agent->lastLog().index
       << "&prevLogTerm=" << _agent->lastLog().term;

  // Ask everyone for their vote
  for (arangodb::consensus::id_t i = 0; i < config().endpoints.size(); ++i) {
    if (i != _id && endpoint(i) != "") {
      auto headerFields =
          std::make_unique<std::unordered_map<std::string, std::string>>();
      operationIDs[i] = arangodb::ClusterComm::instance()->asyncRequest(
          "1", 1, config().endpoints[i], GeneralRequest::RequestType::GET,
          path.str(), std::make_shared<std::string>(body), headerFields,
          nullptr, config().minPing, true);
    }
  }

  // Wait randomized timeout
  std::this_thread::sleep_for(
      sleepFor(.5 * config().minPing, .8 * config().minPing));

  // Collect votes
  // FIXME: This code can be improved: One can wait for an arbitrary
  // result by creating a coordinatorID and waiting for a pattern.
  for (arangodb::consensus::id_t i = 0; i < config().endpoints.size(); ++i) {
    if (i != _id && endpoint(i) != "") {
      ClusterCommResult res =
          arangodb::ClusterComm::instance()->enquire(operationIDs[i]);

      if (res.status == CL_COMM_SENT) {  // Request successfully sent
        res = arangodb::ClusterComm::instance()->wait(
            "1", 1, operationIDs[i], "1");
        std::shared_ptr<Builder> body = res.result->getBodyVelocyPack();
        if (body->isEmpty()) {  // body empty
          continue;
        } else {
          if (body->slice().isObject()) {  // body
            VPackSlice slc = body->slice();
            if (slc.hasKey("term") && slc.hasKey("voteGranted")) {  // OK
              term_t t = slc.get("term").getUInt();
              if (t > _term) {  // follow?
                follow(t);
                break;
              }
              votes[i] = slc.get("voteGranted").getBool();  // Get vote
            }
          }
        }
      } else {  // Request failed
        votes[i] = false;
      }
    }
  }

  // Count votes
  size_t yea = 0;
  for (size_t i = 0; i < size(); ++i) {
    if (votes[i]) {
      yea++;
    }
  }

  // Evaluate election results
  if (yea > size() / 2) {
    lead(votes);
  } else {
    follow(_term);
  }

}

/// Start clean shutdown
void Constituent::beginShutdown() {

  _notifier.reset();
  Thread::beginShutdown();

  CONDITION_LOCKER(guard, _cv);
  guard.broadcast();

}

/// Start operation
bool Constituent::start(TRI_vocbase_t* vocbase,
                        aql::QueryRegistry* queryRegistry) {

  _vocbase = vocbase;
  _queryRegistry = queryRegistry;

  return Thread::start();

}

/// Get persisted information and run election process
void Constituent::run() {

  TRI_ASSERT(_vocbase != nullptr);
  auto bindVars = std::make_shared<VPackBuilder>();
  bindVars->openObject();
  bindVars->close();

  // Most recent vote
  std::string const aql("FOR l IN election SORT l._key DESC LIMIT 1 RETURN l");
  arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), bindVars,
                             nullptr, arangodb::aql::PART_MAIN);

  auto queryResult = query.execute(_queryRegistry);
  if (queryResult.code != TRI_ERROR_NO_ERROR) {
    THROW_ARANGO_EXCEPTION_MESSAGE(queryResult.code, queryResult.details);
  }

  VPackSlice result = queryResult.result->slice();

  if (result.isArray()) {
    for (auto const& i : VPackArrayIterator(result)) {
      try {
        _term = i.get("term").getUInt();
        _votedFor =
            static_cast<decltype(_votedFor)>(i.get("voted_for").getUInt());
      } catch (std::exception const&) {
        LOG_TOPIC(ERR, Logger::AGENCY)
            << "Persisted election entries corrupt! Defaulting term,vote (0,0)";
      }
    }
  }

  // Always start off as follower
  while (!this->isStopping() && size() > 1) {

    if (_role == FOLLOWER) {
      bool cast = false;

      {
        MUTEX_LOCKER(guard, _castLock);
        _cast = false;  // New round set not cast vote
      }

      int32_t left = static_cast<int32_t>(1000000.0 * config().minPing), right = static_cast<int32_t>(1000000.0 * config().maxPing);
      long rand_wait = static_cast<long>(RandomGenerator::interval(left, right));

      {
        CONDITION_LOCKER(guardv, _cv);
        _cv.wait(rand_wait);
      }

      {
        MUTEX_LOCKER(guard, _castLock);
        cast = _cast;
      }

      if (!cast) {
        candidate();  // Next round, we are running
      }

    } else {
      callElection();  // Run for office
    }

  }

}
<|endoftext|>


<commit_before>/*
 * This file is part of the CN24 semantic segmentation software,
 * copyright (C) 2015 Clemens-Alexander Brust (ikosa dot de at gmail dot com).
 *
 * For licensing information, see the LICENSE file included with this project.
 */
/**
 * @file classifyImage.cpp
 * @brief Application that uses a pretrained net to segment images.
 *
 * @author Clemens-Alexander Brust (ikosa dot de at gmail dot com)
 */

#include <iostream>
#include <fstream>
#include <cstring>
#include <sstream>

#include <cn24.h>

int main (int argc, char* argv[]) {
  if (argc < 6) {
    LOGERROR << "USAGE: " << argv[0] << " <dataset config file> <net config file> <net parameter tensor> <input image file> <output image file>";
    LOGEND;
    return -1;
  }

  // Capture command line arguments
  std::string output_image_fname (argv[5]);
  std::string input_image_fname (argv[4]);
  std::string param_tensor_fname (argv[3]);
  std::string net_config_fname (argv[2]);
  std::string dataset_config_fname (argv[1]);

  // Initialize CN24
  Conv::System::Init();

  // Open network and dataset configuration files
  std::ifstream param_tensor_file(param_tensor_fname,std::ios::in | std::ios::binary);
  std::ifstream net_config_file(net_config_fname,std::ios::in);
  std::ifstream dataset_config_file(dataset_config_fname,std::ios::in);

  if(!param_tensor_file.good()) {
    FATAL("Cannot open param tensor file!");
  }
  if(!net_config_file.good()) {
    FATAL("Cannot open net configuration file!");
  }
  if(!dataset_config_file.good()) {
    FATAL("Cannot open dataset configuration file!");
  }

  // Parse network configuration file
  Conv::ConfigurableFactory* factory = new Conv::ConfigurableFactory(net_config_file, 238238, false);
  // Parse dataset configuration file
  Conv::TensorStreamDataset* dataset = Conv::TensorStreamDataset::CreateFromConfiguration(dataset_config_file, true);
  unsigned int CLASSES = dataset->GetClasses();

  // Load image
  Conv::Tensor original_data_tensor(input_image_fname);

  // Rescale image
  unsigned int width = original_data_tensor.width();
  unsigned int height = original_data_tensor.height();
  if(width & 1)
    width++;
  if(height & 1)
    height++;

  if(width & 2)
    width+=2;
  if(height & 2)
    height+=2;

  if(width & 4)
    width+=4;
  if(height & 4)
    height+=4;

  Conv::Tensor data_tensor(1, width, height, original_data_tensor.maps());
  data_tensor.Clear();
  Conv::Tensor::CopySample(original_data_tensor, 0, data_tensor, 0);

  // Assemble net
	Conv::NetGraph graph;
  Conv::InputLayer input_layer(data_tensor);

	Conv::NetGraphNode input_node(&input_layer);
  input_node.is_input = true;

	graph.AddNode(&input_node);
	bool complete = factory->AddLayers(graph, Conv::NetGraphConnection(&input_node), CLASSES);
	if (!complete)
    FATAL("Failed completeness check, inspect model!");

	graph.Initialize();

  // Load network parameters
  // net.DeserializeParameters(param_tensor_file);

  graph.SetIsTesting(true);
  LOGINFO << "Classifying..." << std::flush;
  graph.FeedForward();

	Conv::Tensor* net_output_tensor = &graph.GetDefaultOutputNode()->output_buffers[0].combined_tensor->data; // &net.buffer(output_layer_id)->data;
  Conv::Tensor image_output_tensor(1, net_output_tensor->width(), net_output_tensor->height(), 3);

  LOGINFO << "Colorizing..." << std::flush;
  dataset->Colorize(*net_output_tensor, image_output_tensor);

  // Recrop image down
  Conv::Tensor small(1, original_data_tensor.width(), original_data_tensor.height(), 3);
  for(unsigned int m = 0; m < 3; m++)
    for(unsigned int y = 0; y < small.height(); y++)
      for(unsigned int x = 0; x < small.width(); x++)
        *small.data_ptr(x,y,m,0) = *image_output_tensor.data_ptr_const(x,y,m,0);

  small.WriteToFile(output_image_fname);

  LOGINFO << "DONE!";
  LOGEND;
  return 0;
}
<commit_msg>classifyImage: Fixes for NetGraph compatibility (2)<commit_after>/*
 * This file is part of the CN24 semantic segmentation software,
 * copyright (C) 2015 Clemens-Alexander Brust (ikosa dot de at gmail dot com).
 *
 * For licensing information, see the LICENSE file included with this project.
 */
/**
 * @file classifyImage.cpp
 * @brief Application that uses a pretrained net to segment images.
 *
 * @author Clemens-Alexander Brust (ikosa dot de at gmail dot com)
 */

#include <iostream>
#include <fstream>
#include <cstring>
#include <sstream>

#include <cn24.h>

int main (int argc, char* argv[]) {
  if (argc < 6) {
    LOGERROR << "USAGE: " << argv[0] << " <dataset config file> <net config file> <net parameter tensor> <input image file> <output image file>";
    LOGEND;
    return -1;
  }

  // Capture command line arguments
  std::string output_image_fname (argv[5]);
  std::string input_image_fname (argv[4]);
  std::string param_tensor_fname (argv[3]);
  std::string net_config_fname (argv[2]);
  std::string dataset_config_fname (argv[1]);

  // Initialize CN24
  Conv::System::Init();

  // Open network and dataset configuration files
  std::ifstream param_tensor_file(param_tensor_fname,std::ios::in | std::ios::binary);
  std::ifstream net_config_file(net_config_fname,std::ios::in);
  std::ifstream dataset_config_file(dataset_config_fname,std::ios::in);

  if(!param_tensor_file.good()) {
    FATAL("Cannot open param tensor file!");
  }
  if(!net_config_file.good()) {
    FATAL("Cannot open net configuration file!");
  }
  if(!dataset_config_file.good()) {
    FATAL("Cannot open dataset configuration file!");
  }

  // Parse network configuration file
  Conv::ConfigurableFactory* factory = new Conv::ConfigurableFactory(net_config_file, 238238, false);
  // Parse dataset configuration file
  Conv::TensorStreamDataset* dataset = Conv::TensorStreamDataset::CreateFromConfiguration(dataset_config_file, true);
  unsigned int CLASSES = dataset->GetClasses();

  // Load image
  Conv::Tensor original_data_tensor(input_image_fname);

  // Rescale image
  unsigned int width = original_data_tensor.width();
  unsigned int height = original_data_tensor.height();
  if(width & 1)
    width++;
  if(height & 1)
    height++;

  if(width & 2)
    width+=2;
  if(height & 2)
    height+=2;

  if(width & 4)
    width+=4;
  if(height & 4)
    height+=4;

  Conv::Tensor data_tensor(1, width, height, original_data_tensor.maps());
  data_tensor.Clear();
  Conv::Tensor::CopySample(original_data_tensor, 0, data_tensor, 0);

  // Assemble net
	Conv::NetGraph graph;
  Conv::InputLayer input_layer(data_tensor);

	Conv::NetGraphNode input_node(&input_layer);
  input_node.is_input = true;

	graph.AddNode(&input_node);
	bool complete = factory->AddLayers(graph, Conv::NetGraphConnection(&input_node), CLASSES);
	if (!complete)
    FATAL("Failed completeness check, inspect model!");

	graph.Initialize();

  // Load network parameters
  graph.DeserializeParameters(param_tensor_file);

  graph.SetIsTesting(true);
  LOGINFO << "Classifying..." << std::flush;
  graph.FeedForward();

	Conv::Tensor* net_output_tensor = &graph.GetDefaultOutputNode()->output_buffers[0].combined_tensor->data; // &net.buffer(output_layer_id)->data;
  Conv::Tensor image_output_tensor(1, net_output_tensor->width(), net_output_tensor->height(), 3);

  LOGINFO << "Colorizing..." << std::flush;
  dataset->Colorize(*net_output_tensor, image_output_tensor);

  // Recrop image down
  Conv::Tensor small(1, original_data_tensor.width(), original_data_tensor.height(), 3);
  for(unsigned int m = 0; m < 3; m++)
    for(unsigned int y = 0; y < small.height(); y++)
      for(unsigned int x = 0; x < small.width(); x++)
        *small.data_ptr(x,y,m,0) = *image_output_tensor.data_ptr_const(x,y,m,0);

  small.WriteToFile(output_image_fname);

  LOGINFO << "DONE!";
  LOGEND;
  return 0;
}
<|endoftext|>


<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 Jan Steemann
////////////////////////////////////////////////////////////////////////////////

#include "Aql/ExecutionStats.h"
#include "Basics/Exceptions.h"

using namespace triagens::aql;
using Json = triagens::basics::Json;
using JsonHelper = triagens::basics::JsonHelper;

////////////////////////////////////////////////////////////////////////////////
/// @brief convert the statistics to VelocyPack
////////////////////////////////////////////////////////////////////////////////

VPackBuilder ExecutionStats::toVelocyPack() const {
  VPackBuilder result;
  VPackObjectBuilder b(&result);
  result.add("writesExecuted", VPackValue(writesExecuted));
  result.add("writesIgnored", VPackValue(writesIgnored));
  result.add("scannedFull", VPackValue(scannedFull));
  result.add("scannedIndex", VPackValue(scannedIndex));
  result.add("filtered", VPackValue(filtered));

  if (fullCount > -1) {
    // fullCount is exceptional. it has a default value of -1 and is
    // not reported with this value
    result.add("fullCount", VPackValue(fullCount));
  }
  return result;
}

VPackBuilder ExecutionStats::toVelocyPackStatic() {
  VPackBuilder result;
  VPackObjectBuilder b(&result);
  result.add("writesExecuted", VPackValue(0));
  result.add("writesIgnored", VPackValue(0));
  result.add("scannedFull", VPackValue(0));
  result.add("scannedIndex", VPackValue(0));
  result.add("filtered", VPackValue(0));
  result.add("fullCount", VPackValue(-1));
  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief convert the statistics to JSON
////////////////////////////////////////////////////////////////////////////////

Json ExecutionStats::toJson() const {
  Json json(Json::Object, 5);
  json.set("writesExecuted", Json(static_cast<double>(writesExecuted)));
  json.set("writesIgnored", Json(static_cast<double>(writesIgnored)));
  json.set("scannedFull", Json(static_cast<double>(scannedFull)));
  json.set("scannedIndex", Json(static_cast<double>(scannedIndex)));
  json.set("filtered", Json(static_cast<double>(filtered)));

  if (fullCount > -1) {
    // fullCount is exceptional. it has a default value of -1 and is
    // not reported with this value
    json.set("fullCount", Json(static_cast<double>(fullCount)));
  }

  return json;
}

Json ExecutionStats::toJsonStatic() {
  Json json(Json::Object, 7);
  json.set("writesExecuted", Json(0.0));
  json.set("writesIgnored", Json(0.0));
  json.set("scannedFull", Json(0.0));
  json.set("scannedIndex", Json(0.0));
  json.set("filtered", Json(0.0));
  json.set("fullCount", Json(-1.0));
  json.set("static", Json(0.0));

  return json;
}

ExecutionStats::ExecutionStats()
    : writesExecuted(0),
      writesIgnored(0),
      scannedFull(0),
      scannedIndex(0),
      filtered(0),
      fullCount(-1) {}

ExecutionStats::ExecutionStats(triagens::basics::Json const& jsonStats) {
  if (!jsonStats.isObject()) {
    THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
                                   "stats is not an object");
  }

  writesExecuted = JsonHelper::checkAndGetNumericValue<int64_t>(
      jsonStats.json(), "writesExecuted");
  writesIgnored = JsonHelper::checkAndGetNumericValue<int64_t>(jsonStats.json(),
                                                               "writesIgnored");
  scannedFull = JsonHelper::checkAndGetNumericValue<int64_t>(jsonStats.json(),
                                                             "scannedFull");
  scannedIndex = JsonHelper::checkAndGetNumericValue<int64_t>(jsonStats.json(),
                                                              "scannedIndex");
  filtered = JsonHelper::checkAndGetNumericValue<int64_t>(jsonStats.json(),
                                                          "filtered");

  // note: fullCount is an optional attribute!
  fullCount =
      JsonHelper::getNumericValue<int64_t>(jsonStats.json(), "fullCount", -1);
}

<commit_msg>proper nesting<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 Jan Steemann
////////////////////////////////////////////////////////////////////////////////

#include "Aql/ExecutionStats.h"
#include "Basics/Exceptions.h"

using namespace triagens::aql;
using Json = triagens::basics::Json;
using JsonHelper = triagens::basics::JsonHelper;

////////////////////////////////////////////////////////////////////////////////
/// @brief convert the statistics to VelocyPack
////////////////////////////////////////////////////////////////////////////////

VPackBuilder ExecutionStats::toVelocyPack() const {
  VPackBuilder result;
  {
    VPackObjectBuilder b(&result);
    result.add("writesExecuted", VPackValue(writesExecuted));
    result.add("writesIgnored", VPackValue(writesIgnored));
    result.add("scannedFull", VPackValue(scannedFull));
    result.add("scannedIndex", VPackValue(scannedIndex));
    result.add("filtered", VPackValue(filtered));

    if (fullCount > -1) {
      // fullCount is exceptional. it has a default value of -1 and is
      // not reported with this value
      result.add("fullCount", VPackValue(fullCount));
    }
  }
  return result;
}

VPackBuilder ExecutionStats::toVelocyPackStatic() {
  VPackBuilder result;
  VPackObjectBuilder b(&result);
  result.add("writesExecuted", VPackValue(0));
  result.add("writesIgnored", VPackValue(0));
  result.add("scannedFull", VPackValue(0));
  result.add("scannedIndex", VPackValue(0));
  result.add("filtered", VPackValue(0));
  result.add("fullCount", VPackValue(-1));
  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief convert the statistics to JSON
////////////////////////////////////////////////////////////////////////////////

Json ExecutionStats::toJson() const {
  Json json(Json::Object, 5);
  json.set("writesExecuted", Json(static_cast<double>(writesExecuted)));
  json.set("writesIgnored", Json(static_cast<double>(writesIgnored)));
  json.set("scannedFull", Json(static_cast<double>(scannedFull)));
  json.set("scannedIndex", Json(static_cast<double>(scannedIndex)));
  json.set("filtered", Json(static_cast<double>(filtered)));

  if (fullCount > -1) {
    // fullCount is exceptional. it has a default value of -1 and is
    // not reported with this value
    json.set("fullCount", Json(static_cast<double>(fullCount)));
  }

  return json;
}

Json ExecutionStats::toJsonStatic() {
  Json json(Json::Object, 7);
  json.set("writesExecuted", Json(0.0));
  json.set("writesIgnored", Json(0.0));
  json.set("scannedFull", Json(0.0));
  json.set("scannedIndex", Json(0.0));
  json.set("filtered", Json(0.0));
  json.set("fullCount", Json(-1.0));
  json.set("static", Json(0.0));

  return json;
}

ExecutionStats::ExecutionStats()
    : writesExecuted(0),
      writesIgnored(0),
      scannedFull(0),
      scannedIndex(0),
      filtered(0),
      fullCount(-1) {}

ExecutionStats::ExecutionStats(triagens::basics::Json const& jsonStats) {
  if (!jsonStats.isObject()) {
    THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
                                   "stats is not an object");
  }

  writesExecuted = JsonHelper::checkAndGetNumericValue<int64_t>(
      jsonStats.json(), "writesExecuted");
  writesIgnored = JsonHelper::checkAndGetNumericValue<int64_t>(jsonStats.json(),
                                                               "writesIgnored");
  scannedFull = JsonHelper::checkAndGetNumericValue<int64_t>(jsonStats.json(),
                                                             "scannedFull");
  scannedIndex = JsonHelper::checkAndGetNumericValue<int64_t>(jsonStats.json(),
                                                              "scannedIndex");
  filtered = JsonHelper::checkAndGetNumericValue<int64_t>(jsonStats.json(),
                                                          "filtered");

  // note: fullCount is an optional attribute!
  fullCount =
      JsonHelper::getNumericValue<int64_t>(jsonStats.json(), "fullCount", -1);
}

<|endoftext|>


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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkConformalFlatteningMeshFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

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

#include "itkMesh.h"
#include "itkLineCell.h"
#include "itkTriangleCell.h"
#include "itkConformalFlatteningMeshFilter.h"

#include <fstream>

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

int itkConformalFlatteningMeshFilterTest(int argc, char *argv[])
{
  if( argc != 6 )
    {
    std::cerr << "Usage: itkConformalFlatteningMeshFilterTest "
     << "vtkInputFilename vtkOutputFilename "
     << "polarCellId scale mapToSphere[0:1]" << std::endl;
    return EXIT_FAILURE;
    }

  const unsigned int pointDimension   = 3;
  const unsigned int maxCellDimension = 2;

  typedef double FloatingPointType;

  typedef itk::DefaultStaticMeshTraits<
    FloatingPointType,
    pointDimension,
    maxCellDimension,
    FloatingPointType,
    FloatingPointType  >       MeshTraits;

  typedef itk::Mesh<
    FloatingPointType,
    pointDimension,
    MeshTraits              >     MeshType;

  typedef MeshType::PointsContainer::ConstIterator PointIterator;

  typedef MeshType::CellType CellType;
  typedef MeshType::CellsContainer::ConstIterator CellIterator;

  typedef CellType::PointIdIterator PointIdIterator;

  typedef itk::TriangleCell< CellType > TriangleCellType;

  //
  // Read mesh file
  //
  std::ifstream inputFile(argv[1]);

  if( !inputFile.is_open() )
    {
    std::cout << "ERROR: Unable to open file" << std::endl;
    std::cout << "       inputFilename= " << argv[1] << std::endl;
    return EXIT_FAILURE;
    }

  // Create a new mesh
  MeshType::Pointer mesh = MeshType::New();

  std::string line;

  while( !inputFile.eof() )
    {
    getline(inputFile,line);
    std::cout << line << std::endl;

    if( line.find("POINTS") != std::string::npos )
      {
      break;
      }
    }

  std::cout << "POINTS line" << std::endl;
  std::cout << line << std::endl;

  std::string subline( line, strlen("POINTS "), line.length() );
  //std::cout << "subline " << subline << std::endl;

  int numberOfPoints = -1;

  if( sscanf(subline.c_str(),"%d",&numberOfPoints) != 1 )
    {
    std::cout << "ERROR: Failed to read numberOfPoints from subline"
      << std::endl;
    std::cout << "       subline= " << subline << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "numberOfPoints= " << numberOfPoints << std::endl;

  if( numberOfPoints < 1 )
    {
    std::cout << "ERROR: numberOfPoints < 1" << std::endl;
    std::cout << "       numberOfPoints= " << numberOfPoints << std::endl;
    return EXIT_FAILURE;
    }

  mesh->GetPoints()->Reserve( numberOfPoints );

  //
  // Load the point coordinates into the itk::Mesh
  //

  double doublePoint[3];
  MeshType::PointType point;
  long pointId = 0;

  for( unsigned int pn=0; pn < numberOfPoints; pn++ )
    {
    inputFile >> point;
    std::cout << point << std::endl;
    mesh->SetPoint( pointId++, point );
    }

/*
  while( !inputFile.eof() )
    {
    getline( inputFile, line );

    if( line.find("POLYGONS") != std::string::npos )
      {
      break;
      }

    if( sscanf( line.c_str(), "%lf %lf %lf", &doublePoint[0],
          &doublePoint[1], &doublePoint[2] ) != 3 )
      {
      std::cout << "ERROR: Cannot read 3 point coordinates from line"
        << std::endl;
      std::cout << "       line= " << line << std::endl;
      return EXIT_FAILURE;
      }

    //std::cout << "doublePoint"
    //<< " " << doublePoint[0]
    //<< " " << doublePoint[1]
    //<< " " << doublePoint[2] << std::endl;

    point[0] = doublePoint[0];
    point[1] = doublePoint[1];
    point[2] = doublePoint[2];

    std::cout << point[0] << " " << point[1] << " " << point[2]
      << std::endl;

    mesh->SetPoint( pointId++, point );
    }
*/
  std::cout << "pointId= " << pointId << std::endl;
  std::cout << "numberOfPoints= " << numberOfPoints << std::endl;

  if( pointId != numberOfPoints )
    {
    std::cout << "ERROR: pointId != numberOfPoints" << std::endl;
    std::cout << "       pointId= " << pointId << std::endl;
    std::cout << "       numberOfPoints= " << numberOfPoints << std::endl;
    return EXIT_FAILURE;
    }

  // Continue searching for the POLYGONS line
  while( !inputFile.eof() && ( line.find("POLYGONS") == std::string::npos ) )
    {
    getline( inputFile, line );
    }

  std::cout << "POLYGONS line" << std::endl;
  std::cout << line << std::endl;

  std::string subline2(line,strlen("POLYGONS "),line.length());
  std::cout << "subline2 " << subline2 << std::endl;

  int numberOfPolygons = -1;

  //
  // Read the number of polygons
  //

  if( sscanf( subline2.c_str(), "%d", &numberOfPolygons ) != 1 )
    {
    std::cout << "ERROR: Failed to read numberOfPolygons from subline2"
      << std::endl;
    std::cout << "       subline2= " << subline2 << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "numberOfPolygons " << numberOfPolygons << std::endl;

  if( numberOfPolygons < 1 )
    {
    std::cout << "ERROR: numberOfPolygons < 1" << std::endl;
    std::cout << "       numberOfPolygons= " << numberOfPolygons
      << std::endl;
    return EXIT_FAILURE;
    }

  mesh->GetCells()->Reserve( numberOfPolygons );

  //
  // Load the polygons into the itk::Mesh
  //

  unsigned long numberOfCellPoints;
  unsigned long ids[3];

  int cellId = 0;
  int numberOfIndices = 0;

  while( !inputFile.eof() )
    {
    getline( inputFile, line );

    if( line.find("DATA") != std::string::npos )
      {
      break;
      }

    if( sscanf( line.c_str(), "%ld %ld %ld %ld", &numberOfCellPoints,
          &ids[0], &ids[1], &ids[2] ) != 4 )
      {
      break;
      }

    numberOfIndices += numberOfCellPoints + 1;

    if( numberOfCellPoints != 3 )
      {
      std::cout << "ERROR: numberOfCellPoints != 3" << std::endl;
      std::cout << "       numberOfCellPoints= " << numberOfCellPoints
        << std::endl;
      return EXIT_FAILURE;
      }

    if( ids[0] < 0 || ids[1] < 0 || ids[2] < 0 )
      {
      std::cout << "ERROR: Incorrect point ids" << std::endl;
      std::cout << "       ids=" << ids[0] << " " << ids[1] << " " << ids[2]
       << std::endl;
      return EXIT_FAILURE;
      }

    if( ids[0] >= numberOfPoints || ids[1] >= numberOfPoints ||
        ids[2] >= numberOfPoints )
      {
      std::cout << "ERROR: Incorrect point ids" << std::endl;
      std::cout << "       ids=" << ids[0] << " " << ids[1] << " " << ids[2]
       << std::endl;
      return EXIT_FAILURE;
      }

    unsigned long pointIds[3];
    pointIds[0] = ids[0];
    pointIds[1] = ids[1];
    pointIds[2] = ids[2];

    MeshType::CellAutoPointer cell;
    TriangleCellType * triangleCell = new TriangleCellType;
    triangleCell->SetPointIds( (unsigned long*)pointIds );

    cell.TakeOwnership( triangleCell );
    mesh->SetCell( cellId, cell );

    cellId++;
    }

  std::cout << "cellId= " << cellId << std::endl;
  std::cout << "numberOfPolygons= " << numberOfPolygons << std::endl;

  inputFile.close();

  if( cellId != numberOfPolygons )
    {
    std::cout << "ERROR: cellId != numberOfPolygons" << std::endl;
    std::cout << "       cellId= " << cellId << std::endl;
    std::cout << "       numberOfPolygons= " << numberOfPolygons
      << std::endl;
    return EXIT_FAILURE;
    }

  //
  // Test itkConformalFlatteningMeshFilter
  //

  typedef itk::ConformalFlatteningMeshFilter< MeshType, MeshType>  FilterType;
  FilterType::Pointer filter = FilterType::New();

  // Connect the inputs
  filter->SetInput( mesh );

  typedef MeshType::CellIdentifier  CellIdentifier;

  CellIdentifier  polarCellId = atoi( argv[3] );
  filter->SetPolarCellIdentifier( polarCellId );

  int mapToSphere = atoi( argv[5] );
  if( mapToSphere == 1 )
    {
    filter->MapToSphere();
    }
  else
    {
    filter->MapToPlane();
    }

  double scale = atof( argv[4] );

  filter->SetScale( scale );

  // Execute the filter
  try
    {
    filter->Update();
    }
  catch( itk::ExceptionObject & excp )
    {
    std::cerr << excp << std::endl;
    return EXIT_FAILURE;
    }

  // Get the Smart Pointer to the Filter Output
  MeshType::Pointer newMesh = filter->GetOutput();

  //
  // Write to file
  //

  std::ofstream outputFile( argv[2] );

  outputFile << "# vtk DataFile Version 2.0" << std::endl;
  outputFile << "Output of the itkConformalFlatteningMeshFilter Test" << std::endl;
  outputFile << "ASCII" << std::endl;
  outputFile << "DATASET POLYDATA" << std::endl;
  outputFile << "POINTS " << numberOfPoints << " float" << std::endl;

  // Write the point coordinates to the file

  PointIterator pointIterator = mesh->GetPoints()->Begin();
  PointIterator pointItEnd = mesh->GetPoints()->End();

  int numberOfPointsWritten = 0;

  while( pointIterator != pointItEnd )
    {
    point = pointIterator.Value();

    outputFile << point[0] << " " << point[1] << " " << point[2]
      << std::endl;

    pointIterator++;
    numberOfPointsWritten++;
    }

  if( numberOfPointsWritten != numberOfPoints )
    {
    std::cout << "ERROR: numberOfPointsWritten != numberOfPoints"
      << std::endl;
    std::cout << "       numberOfPointsWritten= " << numberOfPointsWritten
      << std::endl;
    std::cout << "       numberOfPoints= " << numberOfPoints << std::endl;
    return EXIT_FAILURE;
    }

  outputFile << "POLYGONS " << numberOfPolygons << " "
    << numberOfIndices << std::endl;

  CellIterator cellIt = mesh->GetCells()->Begin();
  CellIterator cellItEnd = mesh->GetCells()->End();

  int numberOfPolygonsWritten = 0;

  for(unsigned int i=0; cellIt != cellItEnd; ++i, ++cellIt)
    {
    CellType * cellptr = cellIt.Value();

    PointIdIterator pntIdIter = cellptr->PointIdsBegin();
    PointIdIterator pntIdEnd = cellptr->PointIdsEnd();

    outputFile << "3";

    while( pntIdIter != pntIdEnd )
      {
      outputFile << " " << *pntIdIter;
      pntIdIter++;
      }

    outputFile << std::endl;
    numberOfPolygonsWritten++;
    }

  if( numberOfPolygonsWritten != numberOfPolygons )
    {
    std::cout << "ERROR: numberOfPolygonsWritten != numberOfPolygons"
      << std::endl;
    std::cout << "       numberOfPolygonsWritten= "
      << numberOfPolygonsWritten << std::endl;
    std::cout << "       numberOfPolygons= " << numberOfPolygons
      << std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;
}

<commit_msg>ENH: Removing commented out code from previous parsing of points from      Version 2.0 of vtkPolyData files.  CVS: BUG: Output files was taking its input from the original mesh. Now it      uses the mesh produced as output of the ConformalFlattening filter.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkConformalFlatteningMeshFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

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

#include "itkMesh.h"
#include "itkLineCell.h"
#include "itkTriangleCell.h"
#include "itkConformalFlatteningMeshFilter.h"

#include <fstream>

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

int itkConformalFlatteningMeshFilterTest(int argc, char *argv[])
{
  if( argc != 6 )
    {
    std::cerr << "Usage: itkConformalFlatteningMeshFilterTest "
     << "vtkInputFilename vtkOutputFilename "
     << "polarCellId scale mapToSphere[0:1]" << std::endl;
    return EXIT_FAILURE;
    }

  const unsigned int pointDimension   = 3;
  const unsigned int maxCellDimension = 2;

  typedef double FloatingPointType;

  typedef itk::DefaultStaticMeshTraits<
    FloatingPointType,
    pointDimension,
    maxCellDimension,
    FloatingPointType,
    FloatingPointType  >       MeshTraits;

  typedef itk::Mesh<
    FloatingPointType,
    pointDimension,
    MeshTraits              >     MeshType;

  typedef MeshType::PointsContainer::ConstIterator PointIterator;

  typedef MeshType::CellType CellType;
  typedef MeshType::CellsContainer::ConstIterator CellIterator;

  typedef CellType::PointIdIterator PointIdIterator;

  typedef itk::TriangleCell< CellType > TriangleCellType;

  //
  // Read mesh file
  //
  std::ifstream inputFile(argv[1]);

  if( !inputFile.is_open() )
    {
    std::cout << "ERROR: Unable to open file" << std::endl;
    std::cout << "       inputFilename= " << argv[1] << std::endl;
    return EXIT_FAILURE;
    }

  // Create a new mesh
  MeshType::Pointer mesh = MeshType::New();

  std::string line;

  while( !inputFile.eof() )
    {
    getline(inputFile,line);
    std::cout << line << std::endl;

    if( line.find("POINTS") != std::string::npos )
      {
      break;
      }
    }

  std::cout << "POINTS line" << std::endl;
  std::cout << line << std::endl;

  std::string subline( line, strlen("POINTS "), line.length() );
  //std::cout << "subline " << subline << std::endl;

  int numberOfPoints = -1;

  if( sscanf(subline.c_str(),"%d",&numberOfPoints) != 1 )
    {
    std::cout << "ERROR: Failed to read numberOfPoints from subline"
      << std::endl;
    std::cout << "       subline= " << subline << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "numberOfPoints= " << numberOfPoints << std::endl;

  if( numberOfPoints < 1 )
    {
    std::cout << "ERROR: numberOfPoints < 1" << std::endl;
    std::cout << "       numberOfPoints= " << numberOfPoints << std::endl;
    return EXIT_FAILURE;
    }

  mesh->GetPoints()->Reserve( numberOfPoints );

  //
  // Load the point coordinates into the itk::Mesh
  //

  double doublePoint[3];
  MeshType::PointType point;
  long pointId = 0;

  for( unsigned int pn=0; pn < numberOfPoints; pn++ )
    {
    inputFile >> point;
    std::cout << point << std::endl;
    mesh->SetPoint( pointId++, point );
    }

  std::cout << "pointId= " << pointId << std::endl;
  std::cout << "numberOfPoints= " << numberOfPoints << std::endl;

  if( pointId != numberOfPoints )
    {
    std::cout << "ERROR: pointId != numberOfPoints" << std::endl;
    std::cout << "       pointId= " << pointId << std::endl;
    std::cout << "       numberOfPoints= " << numberOfPoints << std::endl;
    return EXIT_FAILURE;
    }

  // Continue searching for the POLYGONS line
  while( !inputFile.eof() && ( line.find("POLYGONS") == std::string::npos ) )
    {
    getline( inputFile, line );
    }

  std::cout << "POLYGONS line" << std::endl;
  std::cout << line << std::endl;

  std::string subline2(line,strlen("POLYGONS "),line.length());
  std::cout << "subline2 " << subline2 << std::endl;

  int numberOfPolygons = -1;

  //
  // Read the number of polygons
  //

  if( sscanf( subline2.c_str(), "%d", &numberOfPolygons ) != 1 )
    {
    std::cout << "ERROR: Failed to read numberOfPolygons from subline2"
      << std::endl;
    std::cout << "       subline2= " << subline2 << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "numberOfPolygons " << numberOfPolygons << std::endl;

  if( numberOfPolygons < 1 )
    {
    std::cout << "ERROR: numberOfPolygons < 1" << std::endl;
    std::cout << "       numberOfPolygons= " << numberOfPolygons
      << std::endl;
    return EXIT_FAILURE;
    }

  mesh->GetCells()->Reserve( numberOfPolygons );

  //
  // Load the polygons into the itk::Mesh
  //

  unsigned long numberOfCellPoints;
  unsigned long ids[3];

  int cellId = 0;
  int numberOfIndices = 0;

  while( !inputFile.eof() )
    {
    getline( inputFile, line );

    if( line.find("DATA") != std::string::npos )
      {
      break;
      }

    if( sscanf( line.c_str(), "%ld %ld %ld %ld", &numberOfCellPoints,
          &ids[0], &ids[1], &ids[2] ) != 4 )
      {
      break;
      }

    numberOfIndices += numberOfCellPoints + 1;

    if( numberOfCellPoints != 3 )
      {
      std::cout << "ERROR: numberOfCellPoints != 3" << std::endl;
      std::cout << "       numberOfCellPoints= " << numberOfCellPoints
        << std::endl;
      return EXIT_FAILURE;
      }

    if( ids[0] < 0 || ids[1] < 0 || ids[2] < 0 )
      {
      std::cout << "ERROR: Incorrect point ids" << std::endl;
      std::cout << "       ids=" << ids[0] << " " << ids[1] << " " << ids[2]
       << std::endl;
      return EXIT_FAILURE;
      }

    if( ids[0] >= numberOfPoints || ids[1] >= numberOfPoints ||
        ids[2] >= numberOfPoints )
      {
      std::cout << "ERROR: Incorrect point ids" << std::endl;
      std::cout << "       ids=" << ids[0] << " " << ids[1] << " " << ids[2]
       << std::endl;
      return EXIT_FAILURE;
      }

    unsigned long pointIds[3];
    pointIds[0] = ids[0];
    pointIds[1] = ids[1];
    pointIds[2] = ids[2];

    MeshType::CellAutoPointer cell;
    TriangleCellType * triangleCell = new TriangleCellType;
    triangleCell->SetPointIds( (unsigned long*)pointIds );

    cell.TakeOwnership( triangleCell );
    mesh->SetCell( cellId, cell );

    cellId++;
    }

  std::cout << "cellId= " << cellId << std::endl;
  std::cout << "numberOfPolygons= " << numberOfPolygons << std::endl;

  inputFile.close();

  if( cellId != numberOfPolygons )
    {
    std::cout << "ERROR: cellId != numberOfPolygons" << std::endl;
    std::cout << "       cellId= " << cellId << std::endl;
    std::cout << "       numberOfPolygons= " << numberOfPolygons
      << std::endl;
    return EXIT_FAILURE;
    }

  //
  // Test itkConformalFlatteningMeshFilter
  //

  typedef itk::ConformalFlatteningMeshFilter< MeshType, MeshType>  FilterType;
  FilterType::Pointer filter = FilterType::New();

  // Connect the inputs
  filter->SetInput( mesh );

  typedef MeshType::CellIdentifier  CellIdentifier;

  CellIdentifier  polarCellId = atoi( argv[3] );
  filter->SetPolarCellIdentifier( polarCellId );

  int mapToSphere = atoi( argv[5] );
  if( mapToSphere == 1 )
    {
    filter->MapToSphere();
    }
  else
    {
    filter->MapToPlane();
    }

  double scale = atof( argv[4] );

  filter->SetScale( scale );

  // Execute the filter
  try
    {
    filter->Update();
    }
  catch( itk::ExceptionObject & excp )
    {
    std::cerr << excp << std::endl;
    return EXIT_FAILURE;
    }

  // Get the Smart Pointer to the Filter Output
  MeshType::Pointer newMesh = filter->GetOutput();

  //
  // Write to file
  //

  std::ofstream outputFile( argv[2] );

  outputFile << "# vtk DataFile Version 2.0" << std::endl;
  outputFile << "Output of the itkConformalFlatteningMeshFilter Test" << std::endl;
  outputFile << "ASCII" << std::endl;
  outputFile << "DATASET POLYDATA" << std::endl;
  outputFile << "POINTS " << numberOfPoints << " float" << std::endl;

  // Write the point coordinates to the file

  PointIterator pointIterator = newMesh->GetPoints()->Begin();
  PointIterator pointItEnd = newMesh->GetPoints()->End();

  int numberOfPointsWritten = 0;

  while( pointIterator != pointItEnd )
    {
    point = pointIterator.Value();

    outputFile << point[0] << " " << point[1] << " " << point[2]
      << std::endl;

    pointIterator++;
    numberOfPointsWritten++;
    }

  if( numberOfPointsWritten != numberOfPoints )
    {
    std::cout << "ERROR: numberOfPointsWritten != numberOfPoints"
      << std::endl;
    std::cout << "       numberOfPointsWritten= " << numberOfPointsWritten
      << std::endl;
    std::cout << "       numberOfPoints= " << numberOfPoints << std::endl;
    return EXIT_FAILURE;
    }

  outputFile << "POLYGONS " << numberOfPolygons << " "
    << numberOfIndices << std::endl;

  CellIterator cellIt = newMesh->GetCells()->Begin();
  CellIterator cellItEnd = newMesh->GetCells()->End();

  int numberOfPolygonsWritten = 0;

  for(unsigned int i=0; cellIt != cellItEnd; ++i, ++cellIt)
    {
    CellType * cellptr = cellIt.Value();

    PointIdIterator pntIdIter = cellptr->PointIdsBegin();
    PointIdIterator pntIdEnd = cellptr->PointIdsEnd();

    outputFile << "3";

    while( pntIdIter != pntIdEnd )
      {
      outputFile << " " << *pntIdIter;
      pntIdIter++;
      }

    outputFile << std::endl;
    numberOfPolygonsWritten++;
    }

  if( numberOfPolygonsWritten != numberOfPolygons )
    {
    std::cout << "ERROR: numberOfPolygonsWritten != numberOfPolygons"
      << std::endl;
    std::cout << "       numberOfPolygonsWritten= "
      << numberOfPolygonsWritten << std::endl;
    std::cout << "       numberOfPolygons= " << numberOfPolygons
      << std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;
}

<|endoftext|>