<commit_before>//TODO: 0 size state != rule-local feature, i.e. still may depend on source span loc/context.  identify truly rule-local features so if we want they can be added to grammar rules (minor speedup)

#include <boost/lexical_cast.hpp>
#include "ff.h"

#include "tdict.h"
#include "hg.h"

using namespace std;

FeatureFunction::~FeatureFunction() {}

void FeatureFunction::FinalTraversalFeatures(const void* ant_state,
                                             SparseVector<double>* features) const {
  (void) ant_state;
  (void) features;
}

string FeatureFunction::usage_helper(std::string const& name,std::string const& params,std::string const& details,bool sp,bool sd) {
  string r=name;
  if (sp) {
    r+=": ";
    r+=params;
  }
  if (sd) {
    r+="\n";
    r+=details;
  }
  return r;
}

FeatureFunction::Features FeatureFunction::single_feature(WordID feat) {
  return Features(1,feat);
}

FeatureFunction::Features ModelSet::all_features(std::ostream *warn,bool warn0) {
  typedef FeatureFunction::Features FFS;
  FFS ffs;
#define WARNFF(x) do { if (warn) { *warn << "WARNING: "<< x ; *warn<<endl; } } while(0)
  typedef std::map<WordID,string> FFM;
  FFM ff_from;
  for (unsigned i=0;i<models_.size();++i) {
    FeatureFunction const& ff=*models_[i];
    string const& ffname=ff.name;
    FFS si=ff.features();
    if (si.empty()) {
      WARNFF(ffname<<" doesn't yet report any feature IDs - implement features() method?");
    }
    unsigned n0=0;
    for (unsigned j=0;j<si.size();++j) {
      WordID fid=si[j];
      if (!fid) ++n0;
      if (fid >= weights_.size())
        weights_.resize(fid+1);
      if (warn0 || fid) {
        pair<FFM::iterator,bool> i_new=ff_from.insert(FFM::value_type(fid,ffname));
        if (i_new.second) {
          if (fid)
            ffs.push_back(fid);
          else
            WARNFF("Feature id 0 for "<<ffname<<" (models["<<i<<"]) - probably no weight provided.  Don't freeze feature ids to see the name");
        } else {
          WARNFF(ffname<<" (models["<<i<<"]) tried to define feature "<<FD::Convert(fid)<<" already defined earlier by "<<i_new.first->second);
        }
      }
    }
    if (n0)
      WARNFF(ffname<<" (models["<<i<<"]) had "<<n0<<" unused features (--no_freeze_feature_set to see them)");
  }
  return ffs;
#undef WARNFF
}

void ModelSet::show_features(std::ostream &out,std::ostream &warn,bool warn_zero_wt)
{
  typedef FeatureFunction::Features FFS;
  FFS ffs=all_features(&warn);
  out << "Weight  Feature\n";
  for (unsigned i=0;i<ffs.size();++i) {
    WordID fid=ffs[i];
    string const& fname=FD::Convert(fid);
    double wt=weights_[fid];
    if (warn_zero_wt && wt==0)
      warn<<"WARNING: "<<fname<<" has 0 weight."<<endl;
    out << wt << "  " << fname<<endl;
  }

}

// Hiero and Joshua use log_10(e) as the value, so I do to
WordPenalty::WordPenalty(const string& param) :
    fid_(FD::Convert("WordPenalty")),
    value_(-1.0 / log(10)) {
  if (!param.empty()) {
    cerr << "Warning WordPenalty ignoring parameter: " << param << endl;
  }
}

void WordPenalty::TraversalFeaturesImpl(const SentenceMetadata& smeta,
                                        const Hypergraph::Edge& edge,
                                        const std::vector<const void*>& ant_states,
                                        SparseVector<double>* features,
                                        SparseVector<double>* estimated_features,
                                        void* state) const {
  (void) smeta;
  (void) ant_states;
  (void) state;
  (void) estimated_features;
  features->set_value(fid_, edge.rule_->EWords() * value_);
}

SourceWordPenalty::SourceWordPenalty(const string& param) :
    fid_(FD::Convert("SourceWordPenalty")),
    value_(-1.0 / log(10)) {
  if (!param.empty()) {
    cerr << "Warning SourceWordPenalty ignoring parameter: " << param << endl;
  }
}

FeatureFunction::Features SourceWordPenalty::features() const {
  return single_feature(fid_);
}

FeatureFunction::Features WordPenalty::features() const {
  return single_feature(fid_);
}

void SourceWordPenalty::TraversalFeaturesImpl(const SentenceMetadata& smeta,
                                        const Hypergraph::Edge& edge,
                                        const std::vector<const void*>& ant_states,
                                        SparseVector<double>* features,
                                        SparseVector<double>* estimated_features,
                                        void* state) const {
  (void) smeta;
  (void) ant_states;
  (void) state;
  (void) estimated_features;
  features->set_value(fid_, edge.rule_->FWords() * value_);
}

ArityPenalty::ArityPenalty(const std::string& param) :
    value_(-1.0 / log(10)) {
  string fname = "Arity_";
  unsigned MAX=DEFAULT_MAX_ARITY;
  using namespace boost;
  if (!param.empty())
    MAX=lexical_cast<unsigned>(param);
  for (unsigned i = 0; i <= MAX; ++i) {
    WordID fid=FD::Convert(fname+lexical_cast<string>(i));
    fids_.push_back(fid);
  }
  while (!fids_.empty() && fids_.back()==0) fids_.pop_back(); // pretty up features vector in case FD was frozen.  doesn't change anything
}

FeatureFunction::Features ArityPenalty::features() const {
  return Features(fids_.begin(),fids_.end());
}

void ArityPenalty::TraversalFeaturesImpl(const SentenceMetadata& smeta,
                                         const Hypergraph::Edge& edge,
                                         const std::vector<const void*>& ant_states,
                                         SparseVector<double>* features,
                                         SparseVector<double>* estimated_features,
                                         void* state) const {
  (void) smeta;
  (void) ant_states;
  (void) state;
  (void) estimated_features;
  unsigned a=edge.Arity();
  features->set_value(a<fids_.size()?fids_[a]:0, value_);
}

ModelSet::ModelSet(const vector<double>& w, const vector<const FeatureFunction*>& models) :
    models_(models),
    weights_(w),
    state_size_(0),
    model_state_pos_(models.size()) {
  for (int i = 0; i < models_.size(); ++i) {
    model_state_pos_[i] = state_size_;
    state_size_ += models_[i]->NumBytesContext();
  }
}

void ModelSet::AddFeaturesToEdge(const SentenceMetadata& smeta,
                                 const Hypergraph& /* hg */,
                                 const vector<string>& node_states,
                                 Hypergraph::Edge* edge,
                                 string* context,
                                 prob_t* combination_cost_estimate) const {
  context->resize(state_size_);
  memset(&(*context)[0], 0, state_size_);
  SparseVector<double> est_vals;  // only computed if combination_cost_estimate is non-NULL
  if (combination_cost_estimate) *combination_cost_estimate = prob_t::One();
  for (int i = 0; i < models_.size(); ++i) {
    const FeatureFunction& ff = *models_[i];
    void* cur_ff_context = NULL;
    vector<const void*> ants(edge->tail_nodes_.size());
    bool has_context = ff.NumBytesContext() > 0;
    if (has_context) {
      int spos = model_state_pos_[i];
      cur_ff_context = &(*context)[spos];
      for (int i = 0; i < ants.size(); ++i) {
        ants[i] = &node_states[edge->tail_nodes_[i]][spos];
      }
    }
    ff.TraversalFeatures(smeta, *edge, ants, &edge->feature_values_, &est_vals, cur_ff_context);
  }
  if (combination_cost_estimate)
    combination_cost_estimate->logeq(est_vals.dot(weights_));
  edge->edge_prob_.logeq(edge->feature_values_.dot(weights_));
}

void ModelSet::AddFinalFeatures(const std::string& state, Hypergraph::Edge* edge) const {
  assert(1 == edge->rule_->Arity());

  for (int i = 0; i < models_.size(); ++i) {
    const FeatureFunction& ff = *models_[i];
    const void* ant_state = NULL;
    bool has_context = ff.NumBytesContext() > 0;
    if (has_context) {
      int spos = model_state_pos_[i];
      ant_state = &state[spos];
    }
    ff.FinalTraversalFeatures(ant_state, &edge->feature_values_);
  }
  edge->edge_prob_.logeq(edge->feature_values_.dot(weights_));
}

<commit_msg>warn 0 fid if warn 0 wt<commit_after>//TODO: 0 size state != rule-local feature, i.e. still may depend on source span loc/context.  identify truly rule-local features so if we want they can be added to grammar rules (minor speedup)

#include <boost/lexical_cast.hpp>
#include "ff.h"

#include "tdict.h"
#include "hg.h"

using namespace std;

FeatureFunction::~FeatureFunction() {}

void FeatureFunction::FinalTraversalFeatures(const void* ant_state,
                                             SparseVector<double>* features) const {
  (void) ant_state;
  (void) features;
}

string FeatureFunction::usage_helper(std::string const& name,std::string const& params,std::string const& details,bool sp,bool sd) {
  string r=name;
  if (sp) {
    r+=": ";
    r+=params;
  }
  if (sd) {
    r+="\n";
    r+=details;
  }
  return r;
}

FeatureFunction::Features FeatureFunction::single_feature(WordID feat) {
  return Features(1,feat);
}

FeatureFunction::Features ModelSet::all_features(std::ostream *warn,bool warn0) {
  typedef FeatureFunction::Features FFS;
  FFS ffs;
#define WARNFF(x) do { if (warn) { *warn << "WARNING: "<< x ; *warn<<endl; } } while(0)
  typedef std::map<WordID,string> FFM;
  FFM ff_from;
  for (unsigned i=0;i<models_.size();++i) {
    FeatureFunction const& ff=*models_[i];
    string const& ffname=ff.name;
    FFS si=ff.features();
    if (si.empty()) {
      WARNFF(ffname<<" doesn't yet report any feature IDs - implement features() method?");
    }
    unsigned n0=0;
    for (unsigned j=0;j<si.size();++j) {
      WordID fid=si[j];
      if (!fid) ++n0;
      if (fid >= weights_.size())
        weights_.resize(fid+1);
      if (warn0 || fid) {
        pair<FFM::iterator,bool> i_new=ff_from.insert(FFM::value_type(fid,ffname));
        if (i_new.second) {
          if (fid)
            ffs.push_back(fid);
          else
            WARNFF("Feature id 0 for "<<ffname<<" (models["<<i<<"]) - probably no weight provided.  Don't freeze feature ids to see the name");
        } else {
          WARNFF(ffname<<" (models["<<i<<"]) tried to define feature "<<FD::Convert(fid)<<" already defined earlier by "<<i_new.first->second);
        }
      }
    }
    if (n0)
      WARNFF(ffname<<" (models["<<i<<"]) had "<<n0<<" unused features (--no_freeze_feature_set to see them)");
  }
  return ffs;
#undef WARNFF
}

void ModelSet::show_features(std::ostream &out,std::ostream &warn,bool warn_zero_wt)
{
  typedef FeatureFunction::Features FFS;
  FFS ffs=all_features(&warn,warn_zero_wt);
  out << "Weight  Feature\n";
  for (unsigned i=0;i<ffs.size();++i) {
    WordID fid=ffs[i];
    string const& fname=FD::Convert(fid);
    double wt=weights_[fid];
    if (warn_zero_wt && wt==0)
      warn<<"WARNING: "<<fname<<" has 0 weight."<<endl;
    out << wt << "  " << fname<<endl;
  }

}

// Hiero and Joshua use log_10(e) as the value, so I do to
WordPenalty::WordPenalty(const string& param) :
    fid_(FD::Convert("WordPenalty")),
    value_(-1.0 / log(10)) {
  if (!param.empty()) {
    cerr << "Warning WordPenalty ignoring parameter: " << param << endl;
  }
}

void WordPenalty::TraversalFeaturesImpl(const SentenceMetadata& smeta,
                                        const Hypergraph::Edge& edge,
                                        const std::vector<const void*>& ant_states,
                                        SparseVector<double>* features,
                                        SparseVector<double>* estimated_features,
                                        void* state) const {
  (void) smeta;
  (void) ant_states;
  (void) state;
  (void) estimated_features;
  features->set_value(fid_, edge.rule_->EWords() * value_);
}

SourceWordPenalty::SourceWordPenalty(const string& param) :
    fid_(FD::Convert("SourceWordPenalty")),
    value_(-1.0 / log(10)) {
  if (!param.empty()) {
    cerr << "Warning SourceWordPenalty ignoring parameter: " << param << endl;
  }
}

FeatureFunction::Features SourceWordPenalty::features() const {
  return single_feature(fid_);
}

FeatureFunction::Features WordPenalty::features() const {
  return single_feature(fid_);
}

void SourceWordPenalty::TraversalFeaturesImpl(const SentenceMetadata& smeta,
                                        const Hypergraph::Edge& edge,
                                        const std::vector<const void*>& ant_states,
                                        SparseVector<double>* features,
                                        SparseVector<double>* estimated_features,
                                        void* state) const {
  (void) smeta;
  (void) ant_states;
  (void) state;
  (void) estimated_features;
  features->set_value(fid_, edge.rule_->FWords() * value_);
}

ArityPenalty::ArityPenalty(const std::string& param) :
    value_(-1.0 / log(10)) {
  string fname = "Arity_";
  unsigned MAX=DEFAULT_MAX_ARITY;
  using namespace boost;
  if (!param.empty())
    MAX=lexical_cast<unsigned>(param);
  for (unsigned i = 0; i <= MAX; ++i) {
    WordID fid=FD::Convert(fname+lexical_cast<string>(i));
    fids_.push_back(fid);
  }
  while (!fids_.empty() && fids_.back()==0) fids_.pop_back(); // pretty up features vector in case FD was frozen.  doesn't change anything
}

FeatureFunction::Features ArityPenalty::features() const {
  return Features(fids_.begin(),fids_.end());
}

void ArityPenalty::TraversalFeaturesImpl(const SentenceMetadata& smeta,
                                         const Hypergraph::Edge& edge,
                                         const std::vector<const void*>& ant_states,
                                         SparseVector<double>* features,
                                         SparseVector<double>* estimated_features,
                                         void* state) const {
  (void) smeta;
  (void) ant_states;
  (void) state;
  (void) estimated_features;
  unsigned a=edge.Arity();
  features->set_value(a<fids_.size()?fids_[a]:0, value_);
}

ModelSet::ModelSet(const vector<double>& w, const vector<const FeatureFunction*>& models) :
    models_(models),
    weights_(w),
    state_size_(0),
    model_state_pos_(models.size()) {
  for (int i = 0; i < models_.size(); ++i) {
    model_state_pos_[i] = state_size_;
    state_size_ += models_[i]->NumBytesContext();
  }
}

void ModelSet::AddFeaturesToEdge(const SentenceMetadata& smeta,
                                 const Hypergraph& /* hg */,
                                 const vector<string>& node_states,
                                 Hypergraph::Edge* edge,
                                 string* context,
                                 prob_t* combination_cost_estimate) const {
  context->resize(state_size_);
  memset(&(*context)[0], 0, state_size_);
  SparseVector<double> est_vals;  // only computed if combination_cost_estimate is non-NULL
  if (combination_cost_estimate) *combination_cost_estimate = prob_t::One();
  for (int i = 0; i < models_.size(); ++i) {
    const FeatureFunction& ff = *models_[i];
    void* cur_ff_context = NULL;
    vector<const void*> ants(edge->tail_nodes_.size());
    bool has_context = ff.NumBytesContext() > 0;
    if (has_context) {
      int spos = model_state_pos_[i];
      cur_ff_context = &(*context)[spos];
      for (int i = 0; i < ants.size(); ++i) {
        ants[i] = &node_states[edge->tail_nodes_[i]][spos];
      }
    }
    ff.TraversalFeatures(smeta, *edge, ants, &edge->feature_values_, &est_vals, cur_ff_context);
  }
  if (combination_cost_estimate)
    combination_cost_estimate->logeq(est_vals.dot(weights_));
  edge->edge_prob_.logeq(edge->feature_values_.dot(weights_));
}

void ModelSet::AddFinalFeatures(const std::string& state, Hypergraph::Edge* edge) const {
  assert(1 == edge->rule_->Arity());

  for (int i = 0; i < models_.size(); ++i) {
    const FeatureFunction& ff = *models_[i];
    const void* ant_state = NULL;
    bool has_context = ff.NumBytesContext() > 0;
    if (has_context) {
      int spos = model_state_pos_[i];
      ant_state = &state[spos];
    }
    ff.FinalTraversalFeatures(ant_state, &edge->feature_values_);
  }
  edge->edge_prob_.logeq(edge->feature_values_.dot(weights_));
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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.
 */

#include "otbConfigurationManager.h"

#include "otbMacro.h"
#include "otbLogger.h"

#include "itkMultiThreader.h"
#include "itksys/SystemTools.hxx"

#ifdef _OPENMP
#include <omp.h>
#endif

#include <cstdlib>
#include <algorithm>
#include <string>

namespace otb
{

std::string ConfigurationManager::GetDEMDirectory()
{
  std::string svalue;
  itksys::SystemTools::GetEnv("OTB_DEM_DIRECTORY",svalue);
  return svalue;
}

std::string ConfigurationManager::GetGeoidFile()
{
  std::string svalue;
  itksys::SystemTools::GetEnv("OTB_GEOID_FILE",svalue);
  return svalue;
}

ConfigurationManager::RAMValueType ConfigurationManager::GetMaxRAMHint()
{
  std::string max_ram_hint;
  if (itksys::SystemTools::GetEnv("OTB_MAX_RAM_HINT", max_ram_hint))
  {
    return std::stoul(max_ram_hint);
  }
  else
  {
    // Default value
    return 256;
  }
}

itk::LoggerBase::PriorityLevelType ConfigurationManager::GetLoggerLevel()
{
  std::string svalue;

  // Default value is INFO
  itk::LoggerBase::PriorityLevelType level = itk::LoggerBase::INFO;

  if(itksys::SystemTools::GetEnv("OTB_LOGGER_LEVEL",svalue))
    {
    if(svalue.compare("DEBUG") == 0)
      {
      level = itk::LoggerBase::DEBUG;
      }
    else if(svalue.compare("INFO") == 0)
      {
      level = itk::LoggerBase::INFO;
      }
    else if(svalue.compare("WARNING") == 0)
      {
      level = itk::LoggerBase::WARNING;
      }
    else if(svalue.compare("CRITICAL") == 0)
      {
      level = itk::LoggerBase::CRITICAL;
      }
    else
      {
      otbLogMacro(Error,<<"Unknown value for OTB_LOGGER_LEVEL_MACRO. Possible values are DEBUG, INFO, WARNING, CRITICAL.");
      }
    }
  return level;
}

int ConfigurationManager::InitOpenMPThreads()
{
  int ret = 1;
#ifdef _OPENMP
  ret = itk::MultiThreader::GetGlobalDefaultNumberOfThreads();
  omp_set_num_threads(ret);
#endif
  return ret;
}

}
<commit_msg>ENH: allow setting on windows with ""<commit_after>/*
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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.
 */

#include "otbConfigurationManager.h"

#include "otbMacro.h"
#include "otbLogger.h"

#include "itkMultiThreader.h"
#include "itksys/SystemTools.hxx"

#ifdef _OPENMP
#include <omp.h>
#endif

#include <cstdlib>
#include <algorithm>
#include <string>

namespace otb
{

std::string ConfigurationManager::GetDEMDirectory()
{
  std::string svalue;
  itksys::SystemTools::GetEnv("OTB_DEM_DIRECTORY",svalue);
  return svalue;
}

std::string ConfigurationManager::GetGeoidFile()
{
  std::string svalue;
  itksys::SystemTools::GetEnv("OTB_GEOID_FILE",svalue);
  return svalue;
}

ConfigurationManager::RAMValueType ConfigurationManager::GetMaxRAMHint()
{
  std::string max_ram_hint;
  if (itksys::SystemTools::GetEnv("OTB_MAX_RAM_HINT", max_ram_hint))
  {
    return std::stoul(max_ram_hint);
  }
  else
  {
    // Default value
    return 256;
  }
}

itk::LoggerBase::PriorityLevelType ConfigurationManager::GetLoggerLevel()
{
  std::string svalue;

  // Default value is INFO
  itk::LoggerBase::PriorityLevelType level = itk::LoggerBase::INFO;
  itksys::SystemTools::GetEnv("OTB_LOGGER_LEVEL",svalue);
  // on windows a variable set with set EX="" will keep the "". We need
  // to remove them.
  svalue = svalue.substr( svalue.find_first_not_of("\"") ,
                          svalue.find_last_not_of("\""));

  if( !svalue.empty() )
    {
    if(svalue.compare("DEBUG") == 0)
      {
      level = itk::LoggerBase::DEBUG;
      }
    else if(svalue.compare("INFO") == 0)
      {
      level = itk::LoggerBase::INFO;
      }
    else if(svalue.compare("WARNING") == 0)
      {
      level = itk::LoggerBase::WARNING;
      }
    else if(svalue.compare("CRITICAL") == 0)
      {
      level = itk::LoggerBase::CRITICAL;
      }
    else
      {
      otbLogMacro(Warning,<<"Unknown value for OTB_LOGGER_LEVEL_MACRO ("
        <<svalue<<"). Possible values are DEBUG, INFO, WARNING, CRITICAL. "
        <<"Level set to INFO.");
      }
    }
  return level;
}

int ConfigurationManager::InitOpenMPThreads()
{
  int ret = 1;
#ifdef _OPENMP
  ret = itk::MultiThreader::GetGlobalDefaultNumberOfThreads();
  omp_set_num_threads(ret);
#endif
  return ret;
}

}
<|endoftext|>


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

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

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

 MMOServer 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 MMOServer.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "anh/service/datastore.h"

#include <memory>
#include <sstream>

#include <boost/date_time/posix_time/posix_time.hpp>

#include <glog/logging.h>

#include <cppconn/exception.h>
#include <cppconn/connection.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/resultset.h>

#include "anh/service/service_description.h"

using namespace anh::service;
using namespace boost::posix_time;
using namespace std;

Datastore::Datastore(shared_ptr<sql::Connection> connection)
    : connection_(connection)
{}

Datastore::~Datastore() {}

std::shared_ptr<Galaxy> Datastore::findGalaxyByName(const std::string& name) const {
    shared_ptr<Galaxy> galaxy = nullptr;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "SELECT * FROM galaxy "
            "WHERE name = ? LIMIT 1"));

        statement->setString(1, name);

        std::unique_ptr<sql::ResultSet> result(statement->executeQuery());

        // if no results are found return a nullptr
        if (!result->next()) {
            return nullptr;
        }

        galaxy = make_shared<Galaxy>(
            result->getUInt("id"),
            result->getUInt("primary_id"),
            result->getString("name"),
            result->getString("version"),
            static_cast<Galaxy::StatusType>(result->getInt("status")),
            result->getString("created_at"),
            result->getString("updated_at"));
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return galaxy;
}

std::shared_ptr<Galaxy> Datastore::createGalaxy(
    const std::string& name,
    const std::string& version) const
{
    shared_ptr<Galaxy> galaxy = nullptr;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "INSERT INTO galaxy(name, version, created_at, status, updated_at) "
            "VALUES(?, ?, ?, NOW(), NOW())"));

        statement->setString(1, name);
        statement->setString(2, version);
        statement->setInt(3, 0);

        // if the statement fails to service return a nullptr
        if (statement->executeUpdate() <= 0) {
            return nullptr;
        }

        statement.reset(connection_->prepareStatement(
            "SELECT * FROM galaxy WHERE id = LAST_INSERT_ID()"));
        std::unique_ptr<sql::ResultSet> result(statement->executeQuery());

        if (!result->next()) {
            return nullptr;
        }

        galaxy = make_shared<Galaxy>(
            result->getUInt("id"),
            result->getUInt("primary_id"),
            result->getString("name"),
            result->getString("version"),
            static_cast<Galaxy::StatusType>(result->getInt("status")),
            result->getString("created_at"),
            result->getString("updated_at"));
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return galaxy;
}
void Datastore::saveGalaxyStatus(int32_t galaxy_id, int32_t status) const
{
    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "update galaxy set status = ? "
            "where id = ?"));

        statement->setInt(1, status);
        statement->setInt(2, galaxy_id);

        statement->executeUpdate();

    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }
}

std::shared_ptr<ServiceDescription> Datastore::createService(const Galaxy& galaxy, const std::string& name, const std::string& type, const std::string& version, const std::string& address, uint16_t tcp_port, uint16_t udp_port, uint16_t ping_port) const {
    shared_ptr<ServiceDescription> service = nullptr;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "INSERT INTO service (galaxy_id, "
                                 "name, "
                                 "type, "
                                 "version, "
                                 "address, "
                                 "tcp_port, "
                                 "udp_port, "
                                 "ping_port, "
                                 "status, "
                                 "last_pulse, "
                                 "created_at, "
                                 "updated_at) "
            "VALUES(?, ?, ?, ?, INET_ATON(?), ?, ?, ?, ?, NOW(), NOW(), NOW())"));

        uint32_t galaxy_id = galaxy.id();

        statement->setInt(1, galaxy_id);
        statement->setString(2, name);
        statement->setString(3, type);
        statement->setString(4, version);
        statement->setString(5, address);
        statement->setUInt(6, static_cast<uint32_t>(tcp_port));
        statement->setUInt(7, static_cast<uint32_t>(udp_port));
        statement->setUInt(8, static_cast<uint32_t>(ping_port));
        statement->setInt(9, static_cast<int32_t>(-1));

        if (! (statement->executeUpdate() > 0)) {
            return nullptr;
        }

        statement.reset(connection_->prepareStatement(
            "SELECT id, galaxy_id, name, type, version, INET_NTOA(address) as address_string, tcp_port, udp_port, ping_port, status, CONVERT(TIMESTAMP(last_pulse), CHAR) as last_pulse_timestamp "
            "FROM service WHERE id = LAST_INSERT_ID()"));
        std::unique_ptr<sql::ResultSet> result(statement->executeQuery());

        if (!result->next()) {
            return nullptr;
        }

        service = make_shared<ServiceDescription>(
            result->getUInt("id"),
            result->getUInt("galaxy_id"),
            result->getString("name"),
            result->getString("type"),
            result->getString("version"),
            result->getString("address_string"),
            result->getUInt("tcp_port"),
            result->getUInt("udp_port"),
            result->getUInt("ping_port")
            );

        service->status(result->getInt("status"));
        service->last_pulse(result->getString("last_pulse_timestamp"));
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return service;
}

void Datastore::saveService(const ServiceDescription& service) const {
    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "UPDATE service SET address = INET_ATON(?), tcp_port = ?, udp_port = ?, ping_port = ?, status = ?, last_pulse = ? WHERE id = ?"));

        statement->setString(1, service.address());
        statement->setUInt(2, service.tcp_port());
        statement->setUInt(3, service.udp_port());
        statement->setUInt(4, service.ping_port());
        statement->setInt(5, service.status());
        statement->setString(6, prepareTimestampForStorage(service.last_pulse()));
        statement->setUInt(7, service.id());
        statement->executeUpdate();
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }
}

std::shared_ptr<Galaxy> Datastore::findGalaxyById(uint32_t id) const {
    std::shared_ptr<Galaxy> galaxy = nullptr;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "SELECT * FROM galaxy "
            "WHERE id = ? LIMIT 1"));

        statement->setUInt(1, id);

        std::unique_ptr<sql::ResultSet> result(statement->executeQuery());

        // if the statement fails to service return a nullptr
        if (!result->next()) {
            return nullptr;
        }

        galaxy = make_shared<Galaxy>(
            result->getUInt("id"),
            result->getUInt("primary_id"),
            result->getString("name"),
            result->getString("version"),
            static_cast<Galaxy::StatusType>(result->getInt("status")),
            result->getString("created_at"),
            result->getString("updated_at"));
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return galaxy;
}

std::shared_ptr<ServiceDescription> Datastore::findServiceById(uint32_t id) const {
    shared_ptr<ServiceDescription> service = nullptr;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "SELECT * FROM service "
            "WHERE id = ? LIMIT 1"));

        statement->setUInt(1, id);

        std::unique_ptr<sql::ResultSet> result(statement->executeQuery());

        // if the statement fails to service return a nullptr
        if (result->next()) {
            service = make_shared<ServiceDescription>(
                result->getUInt("id"),
                result->getUInt("galaxy_id"),
                result->getString("name"),
                result->getString("type"),
                result->getString("version"),
                result->getString("address_string"),
                result->getUInt("tcp_port"),
                result->getUInt("udp_port"),
                result->getUInt("ping_port")
                );

            service->status(result->getInt("status"));
            service->last_pulse(result->getString("last_pulse_timestamp"));
        }
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return service;
}

bool Datastore::deleteServiceById(uint32_t id) const {
    bool deleted = false;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "DELETE FROM service WHERE id = ? "
        ));

        statement->setUInt(1, id);

        deleted = statement->executeUpdate() > 0;

    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return deleted;
}

list<Galaxy> Datastore::getGalaxyList() const {
    std::list<Galaxy> galaxy_list;

    try {
        std::unique_ptr<sql::Statement> statement(connection_->createStatement());
        std::unique_ptr<sql::ResultSet> result(statement->executeQuery(
            "SELECT * FROM galaxy ORDER BY galaxy.name"));

        // Loop through the results and create a map entry for each.
        while (result->next()) {
            galaxy_list.push_back(Galaxy(
                result->getUInt("id"),
                result->getUInt("primary_id"),
                result->getString("name"),
                result->getString("version"),
                static_cast<Galaxy::StatusType>(result->getInt("status")),
                result->getString("created_at"),
                result->getString("updated_at")));
        }
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return galaxy_list;
}

list<ServiceDescription> Datastore::getServiceList(uint32_t galaxy_id) const {
    std::list<ServiceDescription> service_list;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "SELECT id, galaxy_id, name, type, version, address, tcp_port, udp_port, ping_port, status, TIMESTAMP(last_pulse) as last_pulse_timestamp "
            "FROM service WHERE galaxy_id = ? ORDER BY service.type"));

        statement->setUInt(1, galaxy_id);

        std::unique_ptr<sql::ResultSet> result(statement->executeQuery());

        // Loop through the results and create a map entry for each.
        while (result->next()) {
            ServiceDescription service(
                result->getUInt("id"),
                result->getUInt("galaxy_id"),
                result->getString("name"),
                result->getString("type"),
                result->getString("version"),
                result->getString("address"),
                result->getUInt("tcp_port"),
                result->getUInt("udp_port"),
                result->getUInt("ping_port"));
            service.status(result->getInt("status"));
            service.last_pulse(result->getString("last_pulse_timestamp"));

            service_list.push_back(move(service));
        }
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return service_list;
}

std::string Datastore::prepareTimestampForStorage(const std::string& timestamp) const {
    std::stringstream ss;

    boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%Y%m%d%H%M%S%F");
    ss.imbue(std::locale(ss.getloc(), facet));

    ss << boost::posix_time::time_from_string(timestamp);

    return ss.str();
}
<commit_msg>fixed error in last pull request.<commit_after>/*
 This file is part of MMOServer. For more information, visit http://swganh.com

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

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

 MMOServer 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 MMOServer.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "anh/service/datastore.h"

#include <memory>
#include <sstream>

#include <boost/date_time/posix_time/posix_time.hpp>

#include <glog/logging.h>

#include <cppconn/exception.h>
#include <cppconn/connection.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/resultset.h>

#include "anh/service/service_description.h"

using namespace anh::service;
using namespace boost::posix_time;
using namespace std;

Datastore::Datastore(shared_ptr<sql::Connection> connection)
    : connection_(connection)
{}

Datastore::~Datastore() {}

std::shared_ptr<Galaxy> Datastore::findGalaxyByName(const std::string& name) const {
    shared_ptr<Galaxy> galaxy = nullptr;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "SELECT * FROM galaxy "
            "WHERE name = ? LIMIT 1"));

        statement->setString(1, name);

        std::unique_ptr<sql::ResultSet> result(statement->executeQuery());

        // if no results are found return a nullptr
        if (!result->next()) {
            return nullptr;
        }

        galaxy = make_shared<Galaxy>(
            result->getUInt("id"),
            result->getUInt("primary_id"),
            result->getString("name"),
            result->getString("version"),
            static_cast<Galaxy::StatusType>(result->getInt("status")),
            result->getString("created_at"),
            result->getString("updated_at"));
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return galaxy;
}

std::shared_ptr<Galaxy> Datastore::createGalaxy(
    const std::string& name,
    const std::string& version) const
{
    shared_ptr<Galaxy> galaxy = nullptr;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "INSERT INTO galaxy(name, version, status, created_at, updated_at) "
            "VALUES(?, ?, ?, NOW(), NOW())"));

        statement->setString(1, name);
        statement->setString(2, version);
        statement->setInt(3, 0);

        // if the statement fails to service return a nullptr
        if (statement->executeUpdate() <= 0) {
            return nullptr;
        }

        statement.reset(connection_->prepareStatement(
            "SELECT * FROM galaxy WHERE id = LAST_INSERT_ID()"));
        std::unique_ptr<sql::ResultSet> result(statement->executeQuery());

        if (!result->next()) {
            return nullptr;
        }

        galaxy = make_shared<Galaxy>(
            result->getUInt("id"),
            result->getUInt("primary_id"),
            result->getString("name"),
            result->getString("version"),
            static_cast<Galaxy::StatusType>(result->getInt("status")),
            result->getString("created_at"),
            result->getString("updated_at"));
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return galaxy;
}
void Datastore::saveGalaxyStatus(int32_t galaxy_id, int32_t status) const
{
    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "update galaxy set status = ? "
            "where id = ?"));

        statement->setInt(1, status);
        statement->setInt(2, galaxy_id);

        statement->executeUpdate();

    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }
}

std::shared_ptr<ServiceDescription> Datastore::createService(const Galaxy& galaxy, const std::string& name, const std::string& type, const std::string& version, const std::string& address, uint16_t tcp_port, uint16_t udp_port, uint16_t ping_port) const {
    shared_ptr<ServiceDescription> service = nullptr;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "INSERT INTO service (galaxy_id, "
                                 "name, "
                                 "type, "
                                 "version, "
                                 "address, "
                                 "tcp_port, "
                                 "udp_port, "
                                 "ping_port, "
                                 "status, "
                                 "last_pulse, "
                                 "created_at, "
                                 "updated_at) "
            "VALUES(?, ?, ?, ?, INET_ATON(?), ?, ?, ?, ?, NOW(), NOW(), NOW())"));

        uint32_t galaxy_id = galaxy.id();

        statement->setInt(1, galaxy_id);
        statement->setString(2, name);
        statement->setString(3, type);
        statement->setString(4, version);
        statement->setString(5, address);
        statement->setUInt(6, static_cast<uint32_t>(tcp_port));
        statement->setUInt(7, static_cast<uint32_t>(udp_port));
        statement->setUInt(8, static_cast<uint32_t>(ping_port));
        statement->setInt(9, static_cast<int32_t>(-1));

        if (! (statement->executeUpdate() > 0)) {
            return nullptr;
        }

        statement.reset(connection_->prepareStatement(
            "SELECT id, galaxy_id, name, type, version, INET_NTOA(address) as address_string, tcp_port, udp_port, ping_port, status, CONVERT(TIMESTAMP(last_pulse), CHAR) as last_pulse_timestamp "
            "FROM service WHERE id = LAST_INSERT_ID()"));
        std::unique_ptr<sql::ResultSet> result(statement->executeQuery());

        if (!result->next()) {
            return nullptr;
        }

        service = make_shared<ServiceDescription>(
            result->getUInt("id"),
            result->getUInt("galaxy_id"),
            result->getString("name"),
            result->getString("type"),
            result->getString("version"),
            result->getString("address_string"),
            result->getUInt("tcp_port"),
            result->getUInt("udp_port"),
            result->getUInt("ping_port")
            );

        service->status(result->getInt("status"));
        service->last_pulse(result->getString("last_pulse_timestamp"));
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return service;
}

void Datastore::saveService(const ServiceDescription& service) const {
    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "UPDATE service SET address = INET_ATON(?), tcp_port = ?, udp_port = ?, ping_port = ?, status = ?, last_pulse = ? WHERE id = ?"));

        statement->setString(1, service.address());
        statement->setUInt(2, service.tcp_port());
        statement->setUInt(3, service.udp_port());
        statement->setUInt(4, service.ping_port());
        statement->setInt(5, service.status());
        statement->setString(6, prepareTimestampForStorage(service.last_pulse()));
        statement->setUInt(7, service.id());
        statement->executeUpdate();
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }
}

std::shared_ptr<Galaxy> Datastore::findGalaxyById(uint32_t id) const {
    std::shared_ptr<Galaxy> galaxy = nullptr;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "SELECT * FROM galaxy "
            "WHERE id = ? LIMIT 1"));

        statement->setUInt(1, id);

        std::unique_ptr<sql::ResultSet> result(statement->executeQuery());

        // if the statement fails to service return a nullptr
        if (!result->next()) {
            return nullptr;
        }

        galaxy = make_shared<Galaxy>(
            result->getUInt("id"),
            result->getUInt("primary_id"),
            result->getString("name"),
            result->getString("version"),
            static_cast<Galaxy::StatusType>(result->getInt("status")),
            result->getString("created_at"),
            result->getString("updated_at"));
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return galaxy;
}

std::shared_ptr<ServiceDescription> Datastore::findServiceById(uint32_t id) const {
    shared_ptr<ServiceDescription> service = nullptr;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "SELECT * FROM service "
            "WHERE id = ? LIMIT 1"));

        statement->setUInt(1, id);

        std::unique_ptr<sql::ResultSet> result(statement->executeQuery());

        // if the statement fails to service return a nullptr
        if (result->next()) {
            service = make_shared<ServiceDescription>(
                result->getUInt("id"),
                result->getUInt("galaxy_id"),
                result->getString("name"),
                result->getString("type"),
                result->getString("version"),
                result->getString("address_string"),
                result->getUInt("tcp_port"),
                result->getUInt("udp_port"),
                result->getUInt("ping_port")
                );

            service->status(result->getInt("status"));
            service->last_pulse(result->getString("last_pulse_timestamp"));
        }
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return service;
}

bool Datastore::deleteServiceById(uint32_t id) const {
    bool deleted = false;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "DELETE FROM service WHERE id = ? "
        ));

        statement->setUInt(1, id);

        deleted = statement->executeUpdate() > 0;

    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return deleted;
}

list<Galaxy> Datastore::getGalaxyList() const {
    std::list<Galaxy> galaxy_list;

    try {
        std::unique_ptr<sql::Statement> statement(connection_->createStatement());
        std::unique_ptr<sql::ResultSet> result(statement->executeQuery(
            "SELECT * FROM galaxy ORDER BY galaxy.name"));

        // Loop through the results and create a map entry for each.
        while (result->next()) {
            galaxy_list.push_back(Galaxy(
                result->getUInt("id"),
                result->getUInt("primary_id"),
                result->getString("name"),
                result->getString("version"),
                static_cast<Galaxy::StatusType>(result->getInt("status")),
                result->getString("created_at"),
                result->getString("updated_at")));
        }
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return galaxy_list;
}

list<ServiceDescription> Datastore::getServiceList(uint32_t galaxy_id) const {
    std::list<ServiceDescription> service_list;

    try {
        std::unique_ptr<sql::PreparedStatement> statement(connection_->prepareStatement(
            "SELECT id, galaxy_id, name, type, version, address, tcp_port, udp_port, ping_port, status, TIMESTAMP(last_pulse) as last_pulse_timestamp "
            "FROM service WHERE galaxy_id = ? ORDER BY service.type"));

        statement->setUInt(1, galaxy_id);

        std::unique_ptr<sql::ResultSet> result(statement->executeQuery());

        // Loop through the results and create a map entry for each.
        while (result->next()) {
            ServiceDescription service(
                result->getUInt("id"),
                result->getUInt("galaxy_id"),
                result->getString("name"),
                result->getString("type"),
                result->getString("version"),
                result->getString("address"),
                result->getUInt("tcp_port"),
                result->getUInt("udp_port"),
                result->getUInt("ping_port"));
            service.status(result->getInt("status"));
            service.last_pulse(result->getString("last_pulse_timestamp"));

            service_list.push_back(move(service));
        }
    } catch(sql::SQLException &e) {
        DLOG(ERROR) << "SQLException at " << __FILE__ << " (" << __LINE__ << ": " << __FUNCTION__ << ")";
        DLOG(ERROR) << "MySQL Error: (" << e.getErrorCode() << ": " << e.getSQLState() << ") " << e.what();
    }

    return service_list;
}

std::string Datastore::prepareTimestampForStorage(const std::string& timestamp) const {
    std::stringstream ss;

    boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%Y%m%d%H%M%S%F");
    ss.imbue(std::locale(ss.getloc(), facet));

    ss << boost::posix_time::time_from_string(timestamp);

    return ss.str();
}
<|endoftext|>


<commit_before>#include "wandererchunk.h"

#include <QMutex>
#include <QImage>
#include <QColor>
#include <QGLWidget>
#include <math.h>
#include "../lib_paysages/camera.h"
#include "../lib_paysages/color.h"
#include "../lib_paysages/euclid.h"
#include "../lib_paysages/tools.h"

WandererChunk::WandererChunk(Renderer* renderer, double x, double z, double size, int nbchunks)
{
    _renderer = renderer;

    _startx = x;
    _startz = z;
    _size = size;
    _overall_step = size * (double)nbchunks;
    _restart_needed = false;

    priority = 0.0;

    _tessellation_max_size = 32;
    _tessellation = new double[(_tessellation_max_size + 1) * (_tessellation_max_size + 1)];
    _tessellation_current_size = 0;
    _tessellation_step = _size / (double)_tessellation_max_size;

    _texture_max_size = 128;
    _texture_current_size = 0;
    _texture = new QImage(1, 1, QImage::Format_ARGB32);
    _texture_id = 0;
    _texture_changed = false;

    maintain();
}

WandererChunk::~WandererChunk()
{
    _lock_data.lock();
    delete _texture;
    delete [] _tessellation;
    _lock_data.unlock();
}

void WandererChunk::render(QGLWidget* widget)
{
    _lock_data.lock();

    if (_texture_changed)
    {
        _texture_changed = false;
        if (_texture_id)
        {
            widget->deleteTexture(_texture_id);
        }
        // TODO Only do the scale if not power-of-two textures are unsupported by GPU
        _texture_id = widget->bindTexture(_texture->scaled(_texture_current_size, _texture_current_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
        //_texture_id = widget->bindTexture(*_texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    }
    else
    {
        glBindTexture(GL_TEXTURE_2D, _texture_id);
    }

    int tessellation_size = _tessellation_current_size;
    double tsize = 1.0 / (double)_tessellation_max_size;

    _lock_data.unlock();

    if (tessellation_size == 0)
    {
        return;
    }

    int tessellation_inc = _tessellation_max_size / (double)tessellation_size;
    for (int j = 0; j < _tessellation_max_size; j += tessellation_inc)
    {
        glBegin(GL_QUAD_STRIP);
        for (int i = 0; i <= _tessellation_max_size; i += tessellation_inc)
        {
            glTexCoord2d(tsize * (double)i, 1.0 - tsize * (double)j);
            glVertex3d(_startx + _tessellation_step * (double)i, _tessellation[j * (_tessellation_max_size + 1) + i], _startz + _tessellation_step * (double)j);
            glTexCoord2d(tsize * (double)i, 1.0 - tsize * (double)(j + tessellation_inc));
            glVertex3d(_startx + _tessellation_step * (double)i, _tessellation[(j + tessellation_inc) * (_tessellation_max_size + 1) + i], _startz + _tessellation_step * (double)(j + tessellation_inc));
        }
        glEnd();
    }
}

void WandererChunk::updatePriority(CameraDefinition* camera)
{
    // Compute new priority
    _lock_data.lock();
    if (camera->location.x > _startx + _overall_step * 0.5)
    {
        _startx += _overall_step;
        _restart_needed = true;
    }
    if (camera->location.z > _startz + _overall_step * 0.5)
    {
        _startz += _overall_step;
        _restart_needed = true;
    }
    if (camera->location.x < _startx - _overall_step * 0.5)
    {
        _startx -= _overall_step;
        _restart_needed = true;
    }
    if (camera->location.z < _startz - _overall_step * 0.5)
    {
        _startz -= _overall_step;
        _restart_needed = true;
    }

    if (_restart_needed || _texture_current_size <= 1)
    {
        priority = 1000.0;
    }
    else if (_tessellation_current_size == _tessellation_max_size && _texture_current_size == _texture_max_size)
    {
        priority = -1000.0;
    }
    else
    {
        double distance, wanted_size;
        Vector3 center;

        center = getCenter();

        distance = v3Norm(v3Sub(camera->location, center));
        distance = distance < 0.1 ? 0.1 : distance;
        wanted_size = (int)ceil(120.0 - distance / 3.0);

        priority = wanted_size - _texture_current_size;
        /*else if (distance < 30.0 && _texture_current_size < _texture_max_size / 8)
        {
            priority += 75.0;
        }
        else if (distance < 15.0 && _texture_current_size < _texture_max_size)
        {
            priority += 50.0;
        }
        else if (distance < 30.0 && _texture_current_size < _texture_max_size / 2)
        {
            priority += 25.0;
        }*/

        if (!cameraIsBoxInView(camera, center, _size, _size, 40.0))
        {
            priority -= 100.0;
        }
    }
    _lock_data.unlock();
}

bool WandererChunk::maintain()
{
    if (_restart_needed)
    {
        _restart_needed = false;

        _lock_data.lock();
        _texture_current_size = 0;
        _tessellation_current_size = 0;
        _lock_data.unlock();
    }

    if (_tessellation_current_size < _tessellation_max_size || _texture_current_size < _texture_max_size)
    {
        // Improve heightmap resolution
        if (_tessellation_current_size < _tessellation_max_size)
        {
            int new_tessellation_size = _tessellation_current_size ? _tessellation_current_size * 4 : 2;
            int old_tessellation_inc = _tessellation_current_size ? _tessellation_max_size / _tessellation_current_size : 1;
            int new_tessellation_inc = _tessellation_max_size / new_tessellation_size;
            for (int j = 0; j <= _tessellation_max_size; j += new_tessellation_inc)
            {
                for (int i = 0; i <= _tessellation_max_size; i += new_tessellation_inc)
                {
                    if (_tessellation_current_size == 0 || i % old_tessellation_inc != 0 || j % old_tessellation_inc != 0)
                    {
                        double height = _renderer->getTerrainHeight(_renderer, _startx + _tessellation_step * (double)i, _startz + _tessellation_step * (double)j);
                        _tessellation[j * (_tessellation_max_size + 1) + i] = height;
                    }
                }
            }

            _lock_data.lock();
            _tessellation_current_size = new_tessellation_size;
            _lock_data.unlock();
        }

        // Improve texture resolution
        if (_texture_current_size < _texture_max_size)
        {
            int new_texture_size = _texture_current_size ? _texture_current_size * 2 : 1;
            double step_size = _texture_current_size ? _size / (double)(new_texture_size) : 0.1;
            //QImage* new_image = new QImage(new_texture_size, new_texture_size, QImage::Format_ARGB32);
            QImage* new_image = new QImage(_texture->scaled(new_texture_size + 1, new_texture_size + 1, Qt::IgnoreAspectRatio, Qt::FastTransformation));
            for (int j = 0; j <= new_texture_size; j++)
            {
                for (int i = 0; i <= new_texture_size; i++)
                {
                    if (_texture_current_size <= 1 || i % 2 != 0 || j % 2 != 0)
                    {
                        Vector3 location = {_startx + step_size * (double)i, 0.0, _startz + step_size * (double)j};
                        Color color = _renderer->applyTextures(_renderer, location, step_size);
                        new_image->setPixel(i, j, colorTo32BitRGBA(&color));
                    }
                }
            }

            _lock_data.lock();
            delete _texture;
            _texture = new_image;
            _texture_current_size = new_texture_size;
            _texture_changed = true;
            _lock_data.unlock();
        }

        return true;
    }
    else
    {
        return false;
    }
}

Vector3 WandererChunk::getCenter()
{
    Vector3 result;

    result.x = _startx + _size / 2.0;
    result.y = 0.0;
    result.z = _startz + _size / 2.0;

    return result;
}
<commit_msg>paysages : Fixed textures color in 3d explorer.<commit_after>#include "wandererchunk.h"

#include <QMutex>
#include <QImage>
#include <QColor>
#include <QGLWidget>
#include <math.h>
#include "../lib_paysages/camera.h"
#include "../lib_paysages/color.h"
#include "../lib_paysages/euclid.h"
#include "../lib_paysages/tools.h"

WandererChunk::WandererChunk(Renderer* renderer, double x, double z, double size, int nbchunks)
{
    _renderer = renderer;

    _startx = x;
    _startz = z;
    _size = size;
    _overall_step = size * (double)nbchunks;
    _restart_needed = false;

    priority = 0.0;

    _tessellation_max_size = 32;
    _tessellation = new double[(_tessellation_max_size + 1) * (_tessellation_max_size + 1)];
    _tessellation_current_size = 0;
    _tessellation_step = _size / (double)_tessellation_max_size;

    _texture_max_size = 128;
    _texture_current_size = 0;
    _texture = new QImage(1, 1, QImage::Format_ARGB32);
    _texture_id = 0;
    _texture_changed = false;

    maintain();
}

WandererChunk::~WandererChunk()
{
    _lock_data.lock();
    delete _texture;
    delete [] _tessellation;
    _lock_data.unlock();
}

void WandererChunk::render(QGLWidget* widget)
{
    _lock_data.lock();

    if (_texture_changed)
    {
        _texture_changed = false;
        if (_texture_id)
        {
            widget->deleteTexture(_texture_id);
        }
        // TODO Only do the scale if not power-of-two textures are unsupported by GPU
        _texture_id = widget->bindTexture(_texture->scaled(_texture_current_size, _texture_current_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
        //_texture_id = widget->bindTexture(*_texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    }
    else
    {
        glBindTexture(GL_TEXTURE_2D, _texture_id);
    }

    int tessellation_size = _tessellation_current_size;
    double tsize = 1.0 / (double)_tessellation_max_size;

    _lock_data.unlock();

    if (tessellation_size == 0)
    {
        return;
    }

    int tessellation_inc = _tessellation_max_size / (double)tessellation_size;
    for (int j = 0; j < _tessellation_max_size; j += tessellation_inc)
    {
        glBegin(GL_QUAD_STRIP);
        for (int i = 0; i <= _tessellation_max_size; i += tessellation_inc)
        {
            glTexCoord2d(tsize * (double)i, 1.0 - tsize * (double)j);
            glVertex3d(_startx + _tessellation_step * (double)i, _tessellation[j * (_tessellation_max_size + 1) + i], _startz + _tessellation_step * (double)j);
            glTexCoord2d(tsize * (double)i, 1.0 - tsize * (double)(j + tessellation_inc));
            glVertex3d(_startx + _tessellation_step * (double)i, _tessellation[(j + tessellation_inc) * (_tessellation_max_size + 1) + i], _startz + _tessellation_step * (double)(j + tessellation_inc));
        }
        glEnd();
    }
}

void WandererChunk::updatePriority(CameraDefinition* camera)
{
    // Compute new priority
    _lock_data.lock();
    if (camera->location.x > _startx + _overall_step * 0.5)
    {
        _startx += _overall_step;
        _restart_needed = true;
    }
    if (camera->location.z > _startz + _overall_step * 0.5)
    {
        _startz += _overall_step;
        _restart_needed = true;
    }
    if (camera->location.x < _startx - _overall_step * 0.5)
    {
        _startx -= _overall_step;
        _restart_needed = true;
    }
    if (camera->location.z < _startz - _overall_step * 0.5)
    {
        _startz -= _overall_step;
        _restart_needed = true;
    }

    if (_restart_needed || _texture_current_size <= 1)
    {
        priority = 1000.0;
    }
    else if (_tessellation_current_size == _tessellation_max_size && _texture_current_size == _texture_max_size)
    {
        priority = -1000.0;
    }
    else
    {
        double distance, wanted_size;
        Vector3 center;

        center = getCenter();

        distance = v3Norm(v3Sub(camera->location, center));
        distance = distance < 0.1 ? 0.1 : distance;
        wanted_size = (int)ceil(120.0 - distance / 3.0);

        priority = wanted_size - _texture_current_size;
        /*else if (distance < 30.0 && _texture_current_size < _texture_max_size / 8)
        {
            priority += 75.0;
        }
        else if (distance < 15.0 && _texture_current_size < _texture_max_size)
        {
            priority += 50.0;
        }
        else if (distance < 30.0 && _texture_current_size < _texture_max_size / 2)
        {
            priority += 25.0;
        }*/

        if (!cameraIsBoxInView(camera, center, _size, _size, 40.0))
        {
            priority -= 100.0;
        }
    }
    _lock_data.unlock();
}

bool WandererChunk::maintain()
{
    if (_restart_needed)
    {
        _restart_needed = false;

        _lock_data.lock();
        _texture_current_size = 0;
        _tessellation_current_size = 0;
        _lock_data.unlock();
    }

    if (_tessellation_current_size < _tessellation_max_size || _texture_current_size < _texture_max_size)
    {
        // Improve heightmap resolution
        if (_tessellation_current_size < _tessellation_max_size)
        {
            int new_tessellation_size = _tessellation_current_size ? _tessellation_current_size * 4 : 2;
            int old_tessellation_inc = _tessellation_current_size ? _tessellation_max_size / _tessellation_current_size : 1;
            int new_tessellation_inc = _tessellation_max_size / new_tessellation_size;
            for (int j = 0; j <= _tessellation_max_size; j += new_tessellation_inc)
            {
                for (int i = 0; i <= _tessellation_max_size; i += new_tessellation_inc)
                {
                    if (_tessellation_current_size == 0 || i % old_tessellation_inc != 0 || j % old_tessellation_inc != 0)
                    {
                        double height = _renderer->getTerrainHeight(_renderer, _startx + _tessellation_step * (double)i, _startz + _tessellation_step * (double)j);
                        _tessellation[j * (_tessellation_max_size + 1) + i] = height;
                    }
                }
            }

            _lock_data.lock();
            _tessellation_current_size = new_tessellation_size;
            _lock_data.unlock();
        }

        // Improve texture resolution
        if (_texture_current_size < _texture_max_size)
        {
            int new_texture_size = _texture_current_size ? _texture_current_size * 2 : 1;
            double step_size = _texture_current_size ? _size / (double)(new_texture_size) : 0.1;
            //QImage* new_image = new QImage(new_texture_size, new_texture_size, QImage::Format_ARGB32);
            QImage* new_image = new QImage(_texture->scaled(new_texture_size + 1, new_texture_size + 1, Qt::IgnoreAspectRatio, Qt::FastTransformation));
            for (int j = 0; j <= new_texture_size; j++)
            {
                for (int i = 0; i <= new_texture_size; i++)
                {
                    if (_texture_current_size <= 1 || i % 2 != 0 || j % 2 != 0)
                    {
                        Vector3 location = {_startx + step_size * (double)i, 0.0, _startz + step_size * (double)j};
                        Color color = _renderer->applyTextures(_renderer, location, step_size);
                        new_image->setPixel(i, j, colorTo32BitBGRA(&color));
                    }
                }
            }

            _lock_data.lock();
            delete _texture;
            _texture = new_image;
            _texture_current_size = new_texture_size;
            _texture_changed = true;
            _lock_data.unlock();
        }

        return true;
    }
    else
    {
        return false;
    }
}

Vector3 WandererChunk::getCenter()
{
    Vector3 result;

    result.x = _startx + _size / 2.0;
    result.y = 0.0;
    result.z = _startz + _size / 2.0;

    return result;
}
<|endoftext|>


<commit_before>#include "addresstablemodel.h"
#include "guiutil.h"
#include "walletmodel.h"
#include "bitcoinunits.h"
#include "optionsmodel.h"
#include "guiconstants.h"

#include "wallet.h"
#include "base58.h"

#include <QFont>
#include <QColor>
#include <QTimer>

const QString AddressTableModel::Send = "S";
const QString AddressTableModel::Receive = "R";

struct AddressTableEntry
{
    enum Type {
        Sending,
        Receiving
    };

    Type type;
    QString label;
    QString address;
    int64 amount;

    AddressTableEntry() {}
    AddressTableEntry(Type type, const QString &label, const QString &address):
        type(type), label(label), address(address) {}
    AddressTableEntry(Type type, const QString &label, const QString &address, uint64 amount):
        type(type), label(label), address(address), amount(amount) {}
};

struct AddressTableEntryLessThan
{
    bool operator()(const AddressTableEntry &a, const AddressTableEntry &b) const
    {
        return a.address < b.address;
    }
    bool operator()(const AddressTableEntry &a, const QString &b) const
    {
        return a.address < b;
    }
    bool operator()(const QString &a, const AddressTableEntry &b) const
    {
        return a < b.address;
    }
};

// Private implementation
class AddressTablePriv
{
public:
    CWallet *wallet;
    QList<AddressTableEntry> cachedAddressTable;
    AddressTableModel *parent;

    AddressTablePriv(CWallet *wallet, AddressTableModel *parent):
        wallet(wallet), parent(parent) {}

    void refreshAddressTable()
    {
        cachedAddressTable.clear();
        {
            LOCK(wallet->cs_wallet);
            std::map<QString, std::vector<COutput> > mapCoins;
            parent->walletModel->listCoins(mapCoins);
            BOOST_FOREACH(const PAIRTYPE(CTxDestination, std::string)& item, wallet->mapAddressBook)
            {
                const CBitcoinAddress& address = item.first;
                const std::string& strName = item.second;
                bool fMine = IsMine(*wallet, address.Get());
                CKeyID addressCKeyID;
                address.GetKeyID(addressCKeyID);
                int64 amount=0;
                BOOST_FOREACH(PAIRTYPE(QString, std::vector<COutput>) coins, mapCoins)
                {
                    QString sWalletAddress = coins.first;
                    if(sWalletAddress.contains(QString(address.ToString().c_str()),Qt::CaseSensitive))
                    {
                      BOOST_FOREACH(const COutput& out, coins.second)
                      {
                          amount += out.tx->vout[out.i].nValue;
                      }
                    }
                }
                cachedAddressTable.append(AddressTableEntry(fMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending,
                                  QString::fromStdString(strName),
                                  QString::fromStdString(address.ToString()),
                                  amount));
            }
        }
    }

    void updateEntry(const QString &address, const QString &label, bool isMine, int status)
    {
        // Find address / label in model
        QList<AddressTableEntry>::iterator lower = qLowerBound(
            cachedAddressTable.begin(), cachedAddressTable.end(), address, AddressTableEntryLessThan());
        QList<AddressTableEntry>::iterator upper = qUpperBound(
            cachedAddressTable.begin(), cachedAddressTable.end(), address, AddressTableEntryLessThan());
        int lowerIndex = (lower - cachedAddressTable.begin());
        int upperIndex = (upper - cachedAddressTable.begin());
        bool inModel = (lower != upper);
        AddressTableEntry::Type newEntryType = isMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending;

        switch(status)
        {
        case CT_NEW:
            if(inModel)
            {
                OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_NOW, but entry is already in model\n");
                break;
            }
            parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex);
            cachedAddressTable.insert(lowerIndex, AddressTableEntry(newEntryType, label, address));
            parent->endInsertRows();
            break;
        case CT_UPDATED:
            if(!inModel)
            {
                OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_UPDATED, but entry is not in model\n");
                break;
            }
            lower->type = newEntryType;
            lower->label = label;
            parent->emitDataChanged(lowerIndex);
            break;
        case CT_DELETED:
            if(!inModel)
            {
                OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_DELETED, but entry is not in model\n");
                break;
            }
            parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
            cachedAddressTable.erase(lower, upper);
            parent->endRemoveRows();
            break;
        }
    }

    int size()
    {
        return cachedAddressTable.size();
    }

    AddressTableEntry *index(int idx)
    {
        if(idx >= 0 && idx < cachedAddressTable.size())
        {
            return &cachedAddressTable[idx];
        }
        else
        {
            return 0;
        }
    }
};

AddressTableModel::AddressTableModel(CWallet *wallet, WalletModel *parent) :
    QAbstractTableModel(parent),walletModel(parent),wallet(wallet),priv(0)
{
    columns << tr("Label") << tr("Address") << tr("Amount");
    priv = new AddressTablePriv(wallet, this);
    priv->refreshAddressTable();

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(refreshAddressTable()));
    timer->start(MODEL_UPDATE_DELAY);
}

AddressTableModel::~AddressTableModel()
{
    delete priv;
}

void AddressTableModel::refreshAddressTable()
{
  priv->refreshAddressTable();
}

int AddressTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return priv->size();
}

int AddressTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return columns.length();
}

QVariant AddressTableModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());

    if(role == Qt::DisplayRole || role == Qt::EditRole)
    {
        switch(index.column())
        {
        case Label:
            if(rec->label.isEmpty() && role == Qt::DisplayRole)
            {
                return tr("(no label)");
            }
            else
            {
                return rec->label;
            }
        case Address:
            return rec->address;
        case Amount:
            int unit = walletModel->getOptionsModel()->getDisplayUnit();
            return BitcoinUnits::format(unit, rec->amount);
        }
    }
    else if (role == Qt::FontRole)
    {
        QFont font;
        if(index.column() == Address)
        {
            font = GUIUtil::bitcoinAddressFont();
        }
        return font;
    }
    else if (role == TypeRole)
    {
        switch(rec->type)
        {
        case AddressTableEntry::Sending:
            return Send;
        case AddressTableEntry::Receiving:
            return Receive;
        default: break;
        }
    }
    return QVariant();
}

bool AddressTableModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
    if(!index.isValid())
        return false;
    AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());

    editStatus = OK;

    if(role == Qt::EditRole)
    {
        switch(index.column())
        {
        case Label:
            wallet->SetAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get(), value.toString().toStdString());
            rec->label = value.toString();
            break;
        case Address:
            // Refuse to set invalid address, set error status and return false
            if(!walletModel->validateAddress(value.toString()))
            {
                editStatus = INVALID_ADDRESS;
                return false;
            }
            // Double-check that we're not overwriting a receiving address
            if(rec->type == AddressTableEntry::Sending)
            {
                {
                    LOCK(wallet->cs_wallet);
                    // Remove old entry
                    wallet->DelAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get());
                    // Add new entry with new address
                    wallet->SetAddressBookName(CBitcoinAddress(value.toString().toStdString()).Get(), rec->label.toStdString());
                }
            }
            break;
        }

        return true;
    }
    return false;
}

QVariant AddressTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Horizontal)
    {
        if(role == Qt::DisplayRole)
        {
            return columns[section];
        }
    }
    return QVariant();
}

Qt::ItemFlags AddressTableModel::flags(const QModelIndex & index) const
{
    if(!index.isValid())
        return 0;
    AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());

    Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
    // Can edit address and label for sending addresses,
    // and only label for receiving addresses.
    if(rec->type == AddressTableEntry::Sending ||
      (rec->type == AddressTableEntry::Receiving && index.column()==Label))
    {
        retval |= Qt::ItemIsEditable;
    }
    return retval;
}

QModelIndex AddressTableModel::index(int row, int column, const QModelIndex & parent) const
{
    Q_UNUSED(parent);
    AddressTableEntry *data = priv->index(row);
    if(data)
    {
        return createIndex(row, column, priv->index(row));
    }
    else
    {
        return QModelIndex();
    }
}

void AddressTableModel::updateEntry(const QString &address, const QString &label, bool isMine, int status)
{
    // Update address book model from Bitcoin core
    priv->updateEntry(address, label, isMine, status);
}

QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address)
{
    std::string strLabel = label.toStdString();
    std::string strAddress = address.toStdString();

    editStatus = OK;

    if(type == Send)
    {
        if(!walletModel->validateAddress(address))
        {
            editStatus = INVALID_ADDRESS;
            return QString();
        }
        // Check for duplicate addresses
        {
            LOCK(wallet->cs_wallet);
            if(wallet->mapAddressBook.count(CBitcoinAddress(strAddress).Get()))
            {
                editStatus = DUPLICATE_ADDRESS;
                return QString();
            }
        }
    }
    else if(type == Receive)
    {
        // Generate a new address to associate with given label
        WalletModel::UnlockContext ctx(walletModel->requestUnlock());
        if(!ctx.isValid())
        {
            // Unlock wallet failed or was cancelled
            editStatus = WALLET_UNLOCK_FAILURE;
            return QString();
        }
        CPubKey newKey;
        if(!wallet->GetKeyFromPool(newKey, true))
        {
            editStatus = KEY_GENERATION_FAILURE;
            return QString();
        }
        strAddress = CBitcoinAddress(newKey.GetID()).ToString();
    }
    else
    {
        return QString();
    }
    // Add entry
    {
        LOCK(wallet->cs_wallet);
        wallet->SetAddressBookName(CBitcoinAddress(strAddress).Get(), strLabel);
    }
    return QString::fromStdString(strAddress);
}

bool AddressTableModel::removeRows(int row, int count, const QModelIndex & parent)
{
    Q_UNUSED(parent);
    AddressTableEntry *rec = priv->index(row);
    if(count != 1 || !rec || rec->type == AddressTableEntry::Receiving)
    {
        // Can only remove one row at a time, and cannot remove rows not in model.
        // Also refuse to remove receiving addresses.
        return false;
    }
    {
        LOCK(wallet->cs_wallet);
        wallet->DelAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get());
    }
    return true;
}

/* Look up label for address in address book, if not found return empty string.
 */
QString AddressTableModel::labelForAddress(const QString &address) const
{
    {
        LOCK(wallet->cs_wallet);
        CBitcoinAddress address_parsed(address.toStdString());
        std::map<CTxDestination, std::string>::iterator mi = wallet->mapAddressBook.find(address_parsed.Get());
        if (mi != wallet->mapAddressBook.end())
        {
            return QString::fromStdString(mi->second);
        }
    }
    return QString();
}

int AddressTableModel::lookupAddress(const QString &address) const
{
    QModelIndexList lst = match(index(0, Address, QModelIndex()),
                                Qt::EditRole, address, 1, Qt::MatchExactly);
    if(lst.isEmpty())
    {
        return -1;
    }
    else
    {
        return lst.at(0).row();
    }
}

void AddressTableModel::emitDataChanged(int idx)
{
    emit dataChanged(index(idx, 0, QModelIndex()), index(idx, columns.length()-1, QModelIndex()));
}
<commit_msg>Fix bug where Address book and Receive address can get swapped<commit_after>#include "addresstablemodel.h"
#include "guiutil.h"
#include "walletmodel.h"
#include "bitcoinunits.h"
#include "optionsmodel.h"
#include "guiconstants.h"

#include "wallet.h"
#include "base58.h"

#include <QFont>
#include <QColor>
#include <QTimer>

const QString AddressTableModel::Send = "S";
const QString AddressTableModel::Receive = "R";

struct AddressTableEntry
{
    enum Type {
        Sending,
        Receiving
    };

    Type type;
    bool updated;
    QString label;
    QString address;
    int64 amount;

    AddressTableEntry() {}
    AddressTableEntry(Type type, const QString &label, const QString &address):
        type(type), label(label), address(address) {}
    AddressTableEntry(Type type, const QString &label, const QString &address, uint64 amount):
        type(type), label(label), address(address), amount(amount) {}
};

struct AddressTableEntryLessThan
{
    bool operator()(const AddressTableEntry &a, const AddressTableEntry &b) const
    {
        return a.address < b.address;
    }
    bool operator()(const AddressTableEntry &a, const QString &b) const
    {
        return a.address < b;
    }
    bool operator()(const QString &a, const AddressTableEntry &b) const
    {
        return a < b.address;
    }
};

// Private implementation
class AddressTablePriv
{
public:
    CWallet *wallet;
    QList<AddressTableEntry> cachedAddressTable;
    AddressTableModel *parent;

    AddressTablePriv(CWallet *wallet, AddressTableModel *parent):
        wallet(wallet), parent(parent) {}

    void refreshAddressTable()
    {
        for(int i=0;i<cachedAddressTable.size();i++)
        {
          cachedAddressTable[i].updated=false;
        }

        {
            LOCK(wallet->cs_wallet);
            std::map<QString, std::vector<COutput> > mapCoins;
            parent->walletModel->listCoins(mapCoins);
            BOOST_FOREACH(const PAIRTYPE(CTxDestination, std::string)& item, wallet->mapAddressBook)
            {
                const CBitcoinAddress& address = item.first;
                const std::string& strName = item.second;
                bool fMine = IsMine(*wallet, address.Get());
                CKeyID addressCKeyID;
                address.GetKeyID(addressCKeyID);
                int64 amount=0;
                BOOST_FOREACH(PAIRTYPE(QString, std::vector<COutput>) coins, mapCoins)
                {
                    QString sWalletAddress = coins.first;
                    if(sWalletAddress.contains(QString(address.ToString().c_str()),Qt::CaseSensitive))
                    {
                      BOOST_FOREACH(const COutput& out, coins.second)
                      {
                          amount += out.tx->vout[out.i].nValue;
                      }
                    }
                }
                //update existing entries
                bool found=false;
                for(int i=0;i<cachedAddressTable.size();i++)
                {
                  if(cachedAddressTable.at(i).address==QString::fromStdString(address.ToString()))
                  {
                    cachedAddressTable[i].label=QString::fromStdString(strName);
                    cachedAddressTable[i].amount=amount;
                    cachedAddressTable[i].updated=true;
                    found=true;
                    break;
                  }
                }
                //add new entries
                if(!found)
                {
                  cachedAddressTable.append(AddressTableEntry(fMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending,
                                  QString::fromStdString(strName),
                                  QString::fromStdString(address.ToString()),
                                  amount));
                  cachedAddressTable.last().updated=true;
                }
            }
        }
        //remove deleted entries
        for(int i=cachedAddressTable.size()-1;i>0;i--)
        {
          if(!cachedAddressTable.at(i).updated)
          {
            cachedAddressTable.removeAt(i);
          }
        }
    }

    void updateEntry(const QString &address, const QString &label, bool isMine, int status)
    {
        // Find address / label in model
        QList<AddressTableEntry>::iterator lower = qLowerBound(
            cachedAddressTable.begin(), cachedAddressTable.end(), address, AddressTableEntryLessThan());
        QList<AddressTableEntry>::iterator upper = qUpperBound(
            cachedAddressTable.begin(), cachedAddressTable.end(), address, AddressTableEntryLessThan());
        int lowerIndex = (lower - cachedAddressTable.begin());
        int upperIndex = (upper - cachedAddressTable.begin());
        bool inModel = (lower != upper);
        AddressTableEntry::Type newEntryType = isMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending;

        switch(status)
        {
        case CT_NEW:
            if(inModel)
            {
                OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_NOW, but entry is already in model\n");
                break;
            }
            parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex);
            cachedAddressTable.insert(lowerIndex, AddressTableEntry(newEntryType, label, address));
            parent->endInsertRows();
            break;
        case CT_UPDATED:
            if(!inModel)
            {
                OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_UPDATED, but entry is not in model\n");
                break;
            }
            lower->type = newEntryType;
            lower->label = label;
            parent->emitDataChanged(lowerIndex);
            break;
        case CT_DELETED:
            if(!inModel)
            {
                OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_DELETED, but entry is not in model\n");
                break;
            }
            parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
            cachedAddressTable.erase(lower, upper);
            parent->endRemoveRows();
            break;
        }
    }

    int size()
    {
        return cachedAddressTable.size();
    }

    AddressTableEntry *index(int idx)
    {
        if(idx >= 0 && idx < cachedAddressTable.size())
        {
            return &cachedAddressTable[idx];
        }
        else
        {
            return 0;
        }
    }
};

AddressTableModel::AddressTableModel(CWallet *wallet, WalletModel *parent) :
    QAbstractTableModel(parent),walletModel(parent),wallet(wallet),priv(0)
{
    columns << tr("Label") << tr("Address") << tr("Amount");
    priv = new AddressTablePriv(wallet, this);
    priv->refreshAddressTable();

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(refreshAddressTable()));
    timer->start(MODEL_UPDATE_DELAY);
}

AddressTableModel::~AddressTableModel()
{
    delete priv;
}

void AddressTableModel::refreshAddressTable()
{
  priv->refreshAddressTable();
}

int AddressTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return priv->size();
}

int AddressTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return columns.length();
}

QVariant AddressTableModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());

    if(role == Qt::DisplayRole || role == Qt::EditRole)
    {
        switch(index.column())
        {
        case Label:
            if(rec->label.isEmpty() && role == Qt::DisplayRole)
            {
                return tr("(no label)");
            }
            else
            {
                return rec->label;
            }
        case Address:
            return rec->address;
        case Amount:
            int unit = walletModel->getOptionsModel()->getDisplayUnit();
            return BitcoinUnits::format(unit, rec->amount);
        }
    }
    else if (role == Qt::FontRole)
    {
        QFont font;
        if(index.column() == Address)
        {
            font = GUIUtil::bitcoinAddressFont();
        }
        return font;
    }
    else if (role == TypeRole)
    {
        switch(rec->type)
        {
        case AddressTableEntry::Sending:
            return Send;
        case AddressTableEntry::Receiving:
            return Receive;
        default: break;
        }
    }
    return QVariant();
}

bool AddressTableModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
    if(!index.isValid())
        return false;
    AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());

    editStatus = OK;

    if(role == Qt::EditRole)
    {
        switch(index.column())
        {
        case Label:
            wallet->SetAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get(), value.toString().toStdString());
            rec->label = value.toString();
            break;
        case Address:
            // Refuse to set invalid address, set error status and return false
            if(!walletModel->validateAddress(value.toString()))
            {
                editStatus = INVALID_ADDRESS;
                return false;
            }
            // Double-check that we're not overwriting a receiving address
            if(rec->type == AddressTableEntry::Sending)
            {
                {
                    LOCK(wallet->cs_wallet);
                    // Remove old entry
                    wallet->DelAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get());
                    // Add new entry with new address
                    wallet->SetAddressBookName(CBitcoinAddress(value.toString().toStdString()).Get(), rec->label.toStdString());
                }
            }
            break;
        }

        return true;
    }
    return false;
}

QVariant AddressTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Horizontal)
    {
        if(role == Qt::DisplayRole)
        {
            return columns[section];
        }
    }
    return QVariant();
}

Qt::ItemFlags AddressTableModel::flags(const QModelIndex & index) const
{
    if(!index.isValid())
        return 0;
    AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());

    Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
    // Can edit address and label for sending addresses,
    // and only label for receiving addresses.
    if(rec->type == AddressTableEntry::Sending ||
      (rec->type == AddressTableEntry::Receiving && index.column()==Label))
    {
        retval |= Qt::ItemIsEditable;
    }
    return retval;
}

QModelIndex AddressTableModel::index(int row, int column, const QModelIndex & parent) const
{
    Q_UNUSED(parent);
    AddressTableEntry *data = priv->index(row);
    if(data)
    {
        return createIndex(row, column, priv->index(row));
    }
    else
    {
        return QModelIndex();
    }
}

void AddressTableModel::updateEntry(const QString &address, const QString &label, bool isMine, int status)
{
    // Update address book model from Bitcoin core
    priv->updateEntry(address, label, isMine, status);
}

QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address)
{
    std::string strLabel = label.toStdString();
    std::string strAddress = address.toStdString();

    editStatus = OK;

    if(type == Send)
    {
        if(!walletModel->validateAddress(address))
        {
            editStatus = INVALID_ADDRESS;
            return QString();
        }
        // Check for duplicate addresses
        {
            LOCK(wallet->cs_wallet);
            if(wallet->mapAddressBook.count(CBitcoinAddress(strAddress).Get()))
            {
                editStatus = DUPLICATE_ADDRESS;
                return QString();
            }
        }
    }
    else if(type == Receive)
    {
        // Generate a new address to associate with given label
        WalletModel::UnlockContext ctx(walletModel->requestUnlock());
        if(!ctx.isValid())
        {
            // Unlock wallet failed or was cancelled
            editStatus = WALLET_UNLOCK_FAILURE;
            return QString();
        }
        CPubKey newKey;
        if(!wallet->GetKeyFromPool(newKey, true))
        {
            editStatus = KEY_GENERATION_FAILURE;
            return QString();
        }
        strAddress = CBitcoinAddress(newKey.GetID()).ToString();
    }
    else
    {
        return QString();
    }
    // Add entry
    {
        LOCK(wallet->cs_wallet);
        wallet->SetAddressBookName(CBitcoinAddress(strAddress).Get(), strLabel);
    }
    return QString::fromStdString(strAddress);
}

bool AddressTableModel::removeRows(int row, int count, const QModelIndex & parent)
{
    Q_UNUSED(parent);
    AddressTableEntry *rec = priv->index(row);
    if(count != 1 || !rec || rec->type == AddressTableEntry::Receiving)
    {
        // Can only remove one row at a time, and cannot remove rows not in model.
        // Also refuse to remove receiving addresses.
        return false;
    }
    {
        LOCK(wallet->cs_wallet);
        wallet->DelAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get());
    }
    return true;
}

/* Look up label for address in address book, if not found return empty string.
 */
QString AddressTableModel::labelForAddress(const QString &address) const
{
    {
        LOCK(wallet->cs_wallet);
        CBitcoinAddress address_parsed(address.toStdString());
        std::map<CTxDestination, std::string>::iterator mi = wallet->mapAddressBook.find(address_parsed.Get());
        if (mi != wallet->mapAddressBook.end())
        {
            return QString::fromStdString(mi->second);
        }
    }
    return QString();
}

int AddressTableModel::lookupAddress(const QString &address) const
{
    QModelIndexList lst = match(index(0, Address, QModelIndex()),
                                Qt::EditRole, address, 1, Qt::MatchExactly);
    if(lst.isEmpty())
    {
        return -1;
    }
    else
    {
        return lst.at(0).row();
    }
}

void AddressTableModel::emitDataChanged(int idx)
{
    emit dataChanged(index(idx, 0, QModelIndex()), index(idx, columns.length()-1, QModelIndex()));
}
<|endoftext|>


<commit_before>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post
    Copyright (C) 2014 Pedro Côrte-Real
    Copyright (C) 2017 Roman Lebedev

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

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

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

#include "decoders/SimpleTiffDecoder.h"
#include "common/Point.h"                 // for iPoint2D
#include "common/RawImage.h"              // for RawImage, RawImageData
#include "decoders/RawDecoderException.h" // for RawDecoderException (ptr o...
#include "io/Buffer.h"                    // for Buffer
#include "tiff/TiffEntry.h"               // for TiffEntry
#include "tiff/TiffIFD.h"                 // for TiffIFD
#include "tiff/TiffTag.h"                 // for TiffTag::IMAGELENGTH, Tiff...

namespace rawspeed {

void SimpleTiffDecoder::prepareForRawDecoding() {
  raw = getIFDWithLargestImage();
  width = raw->getEntry(IMAGEWIDTH)->getU32();
  height = raw->getEntry(IMAGELENGTH)->getU32();
  off = raw->getEntry(STRIPOFFSETS)->getU32();
  c2 = raw->getEntry(STRIPBYTECOUNTS)->getU32();

  if (off > mFile->getSize())
    ThrowRDE("Offset is out of bounds");

  if (c2 > mFile->getSize() - off) {
    mRaw->setError(
        "Warning: byte count larger than file size, file probably truncated.");
  }

  mRaw->dim = iPoint2D(width, height);
  mRaw->createData();
}

} // namespace rawspeed
<commit_msg>SimpleTiffDecoder::prepareForRawDecoding(): better error handling<commit_after>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post
    Copyright (C) 2014 Pedro Côrte-Real
    Copyright (C) 2017 Roman Lebedev

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

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

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

#include "decoders/SimpleTiffDecoder.h"
#include "common/Point.h"                 // for iPoint2D
#include "common/RawImage.h"              // for RawImage, RawImageData
#include "decoders/RawDecoderException.h" // for RawDecoderException (ptr o...
#include "io/Buffer.h"                    // for Buffer
#include "tiff/TiffEntry.h"               // for TiffEntry
#include "tiff/TiffIFD.h"                 // for TiffIFD
#include "tiff/TiffTag.h"                 // for TiffTag::IMAGELENGTH, Tiff...

namespace rawspeed {

void SimpleTiffDecoder::prepareForRawDecoding() {
  raw = getIFDWithLargestImage();
  width = raw->getEntry(IMAGEWIDTH)->getU32();
  height = raw->getEntry(IMAGELENGTH)->getU32();
  off = raw->getEntry(STRIPOFFSETS)->getU32();
  c2 = raw->getEntry(STRIPBYTECOUNTS)->getU32();

  if (!mFile->isValid(off, c2))
    ThrowRDE("Image is truncated.");

  if (0 == width || 0 == height)
    ThrowRDE("Image has zero size.");

  mRaw->dim = iPoint2D(width, height);
  mRaw->createData();
}

} // namespace rawspeed
<|endoftext|>