<commit_before>#ifndef JARNGREIPR_CLEMENTI_GO
#define JARNGREIPR_CLEMENTI_GO
#include <jarngreipr/forcefield/ForceFieldGenerator.hpp>
#include <jarngreipr/geometry/distance.hpp>
#include <jarngreipr/geometry/angle.hpp>
#include <jarngreipr/geometry/dihedral.hpp>
#include <iterator>
#include <iostream>
#include <vector>

namespace jarngreipr
{

template<typename realT>
class ClementiGo final : public IntraChainForceFieldGenerator<realT>
{
  public:
    typedef IntraChainForceFieldGenerator<realT> base_type;
    typedef typename base_type::real_type real_type;
    typedef typename base_type::bead_type bead_type;

  public:

    ClementiGo()
        : contact_threshold_(6.5), k_bond_length_(100.0), k_bond_angle_(20.0),
          k_dihedral_angle_1_(1.0), k_dihedral_angle_3_(0.5), k_intra_go_(0.3)
    {}
    ~ClementiGo() override = default;

    explicit ClementiGo(const real_type th)
        : contact_threshold_(th), k_bond_length_(100.0), k_bond_angle_(20.0),
          k_dihedral_angle_1_(1.0), k_dihedral_angle_3_(0.5), k_intra_go_(0.3)
    {}

    ClementiGo(const real_type threshold,
        const real_type k_bl,   const real_type k_ba,
        const real_type k_dih1, const real_type k_dih3, const real_type k_igo)
        : contact_threshold_(threshold), k_bond_length_(k_bl), k_bond_angle_(k_ba),
          k_dihedral_angle_1_(k_dih1), k_dihedral_angle_3_(k_dih3),
          k_intra_go_(k_igo)
    {}

    // generate parameters and write out to `ostrm`.
    void generate(toml::Table& out,
        const std::vector<std::unique_ptr<bead_type>>& chain) const override;

    bool check_beads_kind(
        const std::vector<std::unique_ptr<bead_type>>& chain) const override;

    real_type& contact_threshold()       noexcept {return contact_threshold_;}
    real_type  contact_threshold() const noexcept {return contact_threshold_;}

  private:

    real_type min_distance_sq(
            const typename bead_type::container_type& lhs,
            const typename bead_type::container_type& rhs) const
    {
        real_type dist2 = std::numeric_limits<real_type>::max();
        for(const auto& l : lhs)
        {
            if(l.element == " H")
            {
                std::cerr << "ignore atom: " << l << std::endl;
                continue;
            }
            for(const auto& r : rhs)
            {
                if(r.element == " H")
                {
                    std::cerr << "ignore atom: " << r << std::endl;
                    continue;
                }
                const auto d2 = distance(l.position, r.position);
                dist2 = std::min(dist2, d2);
            }
        }
        return dist2;
    }

  private:
    real_type contact_threshold_;
    real_type k_bond_length_;
    real_type k_bond_angle_;
    real_type k_dihedral_angle_1_;
    real_type k_dihedral_angle_3_;
    real_type k_intra_go_;
};

template<typename realT>
void ClementiGo<realT>::generate(toml::Table& ff,
        const std::vector<std::unique_ptr<bead_type>>& chain) const
{
    if(!this->check_beads_kind(chain))
    {
        std::cerr << "ClementiGo: stop generating forcefield..." << std::endl;
        return ;
    }

    if(ff.count("local") == 0)
    {
        ff["local"] = toml::Array();
    }

    /* bond-length */ {
        toml::Table bond_length;
        bond_length["interaction"] = toml::String("BondLength");
        bond_length["potential"]   = toml::String("Harmonic");
        bond_length["topology"]    = toml::String("bond");

        toml::Array params;
        for(std::size_t i=0, sz = chain.size() - 1; i<sz; ++i)
        {
            const auto& bead1 = chain.at(i);
            const auto& bead2 = chain.at(i+1);
            const std::size_t i1 = bead1->index();
            const std::size_t i2 = bead2->index();
            toml::Table para;
            para["indices"] = toml::value{i1, i2};
            para["native"]  = distance(bead1->position(), bead2->position());
            para["k"]       = this->k_bond_length_;
            params.push_back(std::move(para));
        }
        bond_length["parameters"] = std::move(params);
        ff["local"].cast<toml::value_t::Array>().push_back(std::move(bond_length));
    }
    /* bond-angle */{
        toml::Table bond_angle;
        bond_angle["interaction"] = toml::String("BondAngle");
        bond_angle["potential"]   = toml::String("Harmonic");
        bond_angle["topology"]    = toml::String("none");

        toml::Array params;
        for(std::size_t i=0, sz = chain.size() - 2; i<sz; ++i)
        {
            const auto& bead1 = chain.at(i);
            const auto& bead2 = chain.at(i+1);
            const auto& bead3 = chain.at(i+2);
            const std::size_t i1 = bead1->index();
            const std::size_t i2 = bead2->index();
            const std::size_t i3 = bead3->index();

            toml::Table para;
            para["indices"] = toml::value{i1, i2, i3};
            para["native"]  = angle(bead1->position(), bead2->position(),
                                    bead3->position());
            para["k"]  = this->k_bond_angle_;
            params.push_back(std::move(para));
        }
        bond_angle["parameters"] = std::move(params);
        ff["local"].cast<toml::value_t::Array>().push_back(std::move(bond_angle));
    }
    /* dihedral-angle */{
        toml::Table dihd_angle;
        dihd_angle["interaction"] = toml::String("DihedralAngle");
        dihd_angle["potential"]   = toml::String("ClementiDihedral");
        dihd_angle["topology"]    = toml::String("none");

        toml::Array params;
        for(std::size_t i=0, sz = chain.size() - 3; i<sz; ++i)
        {
            const auto& bead1 = chain.at(i);
            const auto& bead2 = chain.at(i+1);
            const auto& bead3 = chain.at(i+2);
            const auto& bead4 = chain.at(i+3);
            const std::size_t i1 = bead1->index();
            const std::size_t i2 = bead2->index();
            const std::size_t i3 = bead3->index();
            const std::size_t i4 = bead4->index();

            toml::Table para;
            para["indices"] = toml::value{i1, i2, i3, i4};
            para["native"]  = dihedral_angle(bead1->position(),
                    bead2->position(), bead3->position(), bead4->position());
            para["k1"]  = this->k_dihedral_angle_1_;
            para["k3"]  = this->k_dihedral_angle_3_;
            params.push_back(std::move(para));
        }
        dihd_angle["parameters"] = std::move(params);
        ff["local"].cast<toml::value_t::Array>().push_back(std::move(dihd_angle));
    }

    const real_type th2 = this->contact_threshold_ * this->contact_threshold_;
    /* intra-chain-go-contacts */{
        toml::Table go_contact;
        go_contact["interaction"] = toml::String("BondLength");
        go_contact["potential"]   = toml::String("Go1012Contact");
        go_contact["topology"]    = toml::String("contact");

        toml::Array params;
        for(std::size_t i=0, sz_i = chain.size()-4; i<sz_i; ++i)
        {
            const auto& group1 = chain.at(i)->atoms();
            for(std::size_t j=i+4, sz_j = chain.size(); j<sz_j; ++j)
            {
                const auto& group2 = chain.at(j)->atoms();
                if(this->min_distance_sq(group1, group2))
                {
                    const auto& bead1 = chain.at(i);
                    const auto& bead2 = chain.at(j);
                    const std::size_t i1 = bead1->index();
                    const std::size_t i2 = bead2->index();

                    toml::Table para;
                    para["indices"] = toml::value{i1, i2};
                    para["native"]  = distance(bead1->position(), bead2->position());
                    para["k"]       = this->k_intra_go_;
                    params.push_back(std::move(para));
                }
            }
        }
        go_contact["parameters"]  = std::move(params);
        ff["local"].cast<toml::value_t::Array>().push_back(std::move(go_contact));
    }
    return;
}

template<typename realT>
bool ClementiGo<realT>::check_beads_kind(
        const std::vector<std::unique_ptr<bead_type>>& chain) const
{
    for(const auto& bead : chain)
    {
        if(bead->kind() != "CarbonAlpha")
        {
            std::cerr << "ClementiGo: invalid coarse-grained bead kind: "
                      << bead->kind() << '\n';
            std::cerr << "it allows only CarbonAlpha beads.\n";
            return false;
        }
    }
    return true;
}

}//jarngreipr
#endif /* JARNGREIPR_CLEMENTI_GO */
<commit_msg>fix min_dist_sq in ClementiGo<commit_after>#ifndef JARNGREIPR_CLEMENTI_GO
#define JARNGREIPR_CLEMENTI_GO
#include <jarngreipr/forcefield/ForceFieldGenerator.hpp>
#include <jarngreipr/geometry/distance.hpp>
#include <jarngreipr/geometry/angle.hpp>
#include <jarngreipr/geometry/dihedral.hpp>
#include <iterator>
#include <iostream>
#include <vector>

namespace jarngreipr
{

template<typename realT>
class ClementiGo final : public IntraChainForceFieldGenerator<realT>
{
  public:
    typedef IntraChainForceFieldGenerator<realT> base_type;
    typedef typename base_type::real_type real_type;
    typedef typename base_type::bead_type bead_type;

  public:

    ClementiGo()
        : contact_threshold_(6.5), k_bond_length_(100.0), k_bond_angle_(20.0),
          k_dihedral_angle_1_(1.0), k_dihedral_angle_3_(0.5), k_intra_go_(0.3)
    {}
    ~ClementiGo() override = default;

    explicit ClementiGo(const real_type th)
        : contact_threshold_(th), k_bond_length_(100.0), k_bond_angle_(20.0),
          k_dihedral_angle_1_(1.0), k_dihedral_angle_3_(0.5), k_intra_go_(0.3)
    {}

    ClementiGo(const real_type threshold,
        const real_type k_bl,   const real_type k_ba,
        const real_type k_dih1, const real_type k_dih3, const real_type k_igo)
        : contact_threshold_(threshold), k_bond_length_(k_bl), k_bond_angle_(k_ba),
          k_dihedral_angle_1_(k_dih1), k_dihedral_angle_3_(k_dih3),
          k_intra_go_(k_igo)
    {}

    // generate parameters and write out to `ostrm`.
    void generate(toml::Table& out,
        const std::vector<std::unique_ptr<bead_type>>& chain) const override;

    bool check_beads_kind(
        const std::vector<std::unique_ptr<bead_type>>& chain) const override;

    real_type& contact_threshold()       noexcept {return contact_threshold_;}
    real_type  contact_threshold() const noexcept {return contact_threshold_;}

  private:

    real_type min_distance_sq(
            const typename bead_type::container_type& lhs,
            const typename bead_type::container_type& rhs) const
    {
        real_type dist2 = std::numeric_limits<real_type>::max();
        for(const auto& l : lhs)
        {
            if(l.element == " H")
            {
                continue;
            }
            for(const auto& r : rhs)
            {
                if(r.element == " H")
                {
                    continue;
                }
                const auto d2 = distance_sq(l.position, r.position);
                dist2 = std::min(dist2, d2);
            }
        }
        return dist2;
    }

  private:
    real_type contact_threshold_;
    real_type k_bond_length_;
    real_type k_bond_angle_;
    real_type k_dihedral_angle_1_;
    real_type k_dihedral_angle_3_;
    real_type k_intra_go_;
};

template<typename realT>
void ClementiGo<realT>::generate(toml::Table& ff,
        const std::vector<std::unique_ptr<bead_type>>& chain) const
{
    if(!this->check_beads_kind(chain))
    {
        std::cerr << "ClementiGo: stop generating forcefield..." << std::endl;
        return ;
    }

    if(ff.count("local") == 0)
    {
        ff["local"] = toml::Array();
    }

    /* bond-length */ {
        toml::Table bond_length;
        bond_length["interaction"] = toml::String("BondLength");
        bond_length["potential"]   = toml::String("Harmonic");
        bond_length["topology"]    = toml::String("bond");

        toml::Array params;
        for(std::size_t i=0, sz = chain.size() - 1; i<sz; ++i)
        {
            const auto& bead1 = chain.at(i);
            const auto& bead2 = chain.at(i+1);
            const std::size_t i1 = bead1->index();
            const std::size_t i2 = bead2->index();
            toml::Table para;
            para["indices"] = toml::value{i1, i2};
            para["native"]  = distance(bead1->position(), bead2->position());
            para["k"]       = this->k_bond_length_;
            params.push_back(std::move(para));
        }
        bond_length["parameters"] = std::move(params);
        ff["local"].cast<toml::value_t::Array>().push_back(std::move(bond_length));
    }
    /* bond-angle */{
        toml::Table bond_angle;
        bond_angle["interaction"] = toml::String("BondAngle");
        bond_angle["potential"]   = toml::String("Harmonic");
        bond_angle["topology"]    = toml::String("none");

        toml::Array params;
        for(std::size_t i=0, sz = chain.size() - 2; i<sz; ++i)
        {
            const auto& bead1 = chain.at(i);
            const auto& bead2 = chain.at(i+1);
            const auto& bead3 = chain.at(i+2);
            const std::size_t i1 = bead1->index();
            const std::size_t i2 = bead2->index();
            const std::size_t i3 = bead3->index();

            toml::Table para;
            para["indices"] = toml::value{i1, i2, i3};
            para["native"]  = angle(bead1->position(), bead2->position(),
                                    bead3->position());
            para["k"]  = this->k_bond_angle_;
            params.push_back(std::move(para));
        }
        bond_angle["parameters"] = std::move(params);
        ff["local"].cast<toml::value_t::Array>().push_back(std::move(bond_angle));
    }
    /* dihedral-angle */{
        toml::Table dihd_angle;
        dihd_angle["interaction"] = toml::String("DihedralAngle");
        dihd_angle["potential"]   = toml::String("ClementiDihedral");
        dihd_angle["topology"]    = toml::String("none");

        toml::Array params;
        for(std::size_t i=0, sz = chain.size() - 3; i<sz; ++i)
        {
            const auto& bead1 = chain.at(i);
            const auto& bead2 = chain.at(i+1);
            const auto& bead3 = chain.at(i+2);
            const auto& bead4 = chain.at(i+3);
            const std::size_t i1 = bead1->index();
            const std::size_t i2 = bead2->index();
            const std::size_t i3 = bead3->index();
            const std::size_t i4 = bead4->index();

            toml::Table para;
            para["indices"] = toml::value{i1, i2, i3, i4};
            para["native"]  = dihedral_angle(bead1->position(),
                    bead2->position(), bead3->position(), bead4->position());
            para["k1"]  = this->k_dihedral_angle_1_;
            para["k3"]  = this->k_dihedral_angle_3_;
            params.push_back(std::move(para));
        }
        dihd_angle["parameters"] = std::move(params);
        ff["local"].cast<toml::value_t::Array>().push_back(std::move(dihd_angle));
    }

    const real_type th2 = this->contact_threshold_ * this->contact_threshold_;
    /* intra-chain-go-contacts */{
        toml::Table go_contact;
        go_contact["interaction"] = toml::String("BondLength");
        go_contact["potential"]   = toml::String("Go1012Contact");
        go_contact["topology"]    = toml::String("contact");

        toml::Array params;
        for(std::size_t i=0, sz_i = chain.size()-4; i<sz_i; ++i)
        {
            const auto& group1 = chain.at(i)->atoms();
            for(std::size_t j=i+4, sz_j = chain.size(); j<sz_j; ++j)
            {
                const auto& group2 = chain.at(j)->atoms();
                if(this->min_distance_sq(group1, group2))
                {
                    const auto& bead1 = chain.at(i);
                    const auto& bead2 = chain.at(j);
                    const std::size_t i1 = bead1->index();
                    const std::size_t i2 = bead2->index();

                    toml::Table para;
                    para["indices"] = toml::value{i1, i2};
                    para["native"]  = distance(bead1->position(), bead2->position());
                    para["k"]       = this->k_intra_go_;
                    params.push_back(std::move(para));
                }
            }
        }
        go_contact["parameters"]  = std::move(params);
        ff["local"].cast<toml::value_t::Array>().push_back(std::move(go_contact));
    }
    return;
}

template<typename realT>
bool ClementiGo<realT>::check_beads_kind(
        const std::vector<std::unique_ptr<bead_type>>& chain) const
{
    for(const auto& bead : chain)
    {
        if(bead->kind() != "CarbonAlpha")
        {
            std::cerr << "ClementiGo: invalid coarse-grained bead kind: "
                      << bead->kind() << '\n';
            std::cerr << "it allows only CarbonAlpha beads.\n";
            return false;
        }
    }
    return true;
}

}//jarngreipr
#endif /* JARNGREIPR_CLEMENTI_GO */
<|endoftext|>


<commit_before>/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; version 2 of the License.

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

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software Foundation,
  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */

/**
  @file storage/perfschema/ha_perfschema.cc
  Performance schema storage engine (implementation).
*/

#include "my_global.h"
#include "my_pthread.h"
#include "sql_plugin.h"
#include "mysql/plugin.h"
#include "ha_perfschema.h"
#include "pfs_engine_table.h"
#include "pfs_column_values.h"
#include "pfs_instr_class.h"
#include "pfs_instr.h"

handlerton *pfs_hton= NULL;

static handler* pfs_create_handler(handlerton *hton,
                                   TABLE_SHARE *table,
                                   MEM_ROOT *mem_root)
{
  return new (mem_root) ha_perfschema(hton, table);
}

static int compare_database_names(const char *name1, const char *name2)
{
  if (lower_case_table_names)
    return strcasecmp(name1, name2);
  return strcmp(name1, name2);
}

static const PFS_engine_table_share*
find_table_share(const char *db, const char *name)
{
  DBUG_ENTER("find_table_share");

  if (compare_database_names(db, PERFORMANCE_SCHEMA_str.str) != 0)
    DBUG_RETURN(NULL);

  const PFS_engine_table_share* result;
  result= PFS_engine_table::find_engine_table_share(name);
  DBUG_RETURN(result);
}

static int pfs_init_func(void *p)
{
  DBUG_ENTER("pfs_init_func");

  pfs_hton= reinterpret_cast<handlerton *> (p);

  pfs_hton->state= SHOW_OPTION_YES;
  pfs_hton->create= pfs_create_handler;
  pfs_hton->show_status= pfs_show_status;
  pfs_hton->flags= HTON_ALTER_NOT_SUPPORTED |
    HTON_TEMPORARY_NOT_SUPPORTED |
    HTON_NO_PARTITION;

  /*
    As long as the server implementation keeps using legacy_db_type,
    as for example in mysql_truncate(),
    we can not rely on the fact that different mysqld process will assign
    consistently the same legacy_db_type for a given storage engine name.
    In particular, using different --loose-skip-xxx options between
    ./mysqld --bootstrap
    ./mysqld
    creates bogus .frm forms when bootstrapping the performance schema,
    if we rely on ha_initialize_handlerton to assign a really dynamic value.
    To fix this, a dedicated DB_TYPE is officially assigned to
    the performance schema. See Bug#43039.
  */
  pfs_hton->db_type= DB_TYPE_PERFORMANCE_SCHEMA;

  PFS_engine_table_share::init_all_locks();

  DBUG_RETURN(0);
}

static int pfs_done_func(void *p)
{
  DBUG_ENTER("pfs_done_func");

  pfs_hton= NULL;

  PFS_engine_table_share::delete_all_locks();

  DBUG_RETURN(0);
}

static struct st_mysql_show_var pfs_status_vars[]=
{
  {"Performance_schema_mutex_classes_lost",
    (char*) &mutex_class_lost, SHOW_LONG_NOFLUSH},
  {"Performance_schema_rwlock_classes_lost",
    (char*) &rwlock_class_lost, SHOW_LONG_NOFLUSH},
  {"Performance_schema_cond_classes_lost",
    (char*) &cond_class_lost, SHOW_LONG_NOFLUSH},
  {"Performance_schema_thread_classes_lost",
    (char*) &thread_class_lost, SHOW_LONG_NOFLUSH},
  {"Performance_schema_file_classes_lost",
    (char*) &file_class_lost, SHOW_LONG_NOFLUSH},
  {"Performance_schema_mutex_instances_lost",
    (char*) &mutex_lost, SHOW_LONG},
  {"Performance_schema_rwlock_instances_lost",
    (char*) &rwlock_lost, SHOW_LONG},
  {"Performance_schema_cond_instances_lost",
    (char*) &cond_lost, SHOW_LONG},
  {"Performance_schema_thread_instances_lost",
    (char*) &thread_lost, SHOW_LONG},
  {"Performance_schema_file_instances_lost",
    (char*) &file_lost, SHOW_LONG},
  {"Performance_schema_file_handles_lost",
    (char*) &file_handle_lost, SHOW_LONG},
  {"Performance_schema_locker_lost",
    (char*) &locker_lost, SHOW_LONG},
  /* table shares, can be flushed */
  {"Performance_schema_table_instances_lost",
    (char*) &table_share_lost, SHOW_LONG},
  /* table handles, can be flushed */
  {"Performance_schema_table_handles_lost",
    (char*) &table_lost, SHOW_LONG},
  {NullS, NullS, SHOW_LONG}
};

struct st_mysql_storage_engine pfs_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };

const char* pfs_engine_name= "PERFORMANCE_SCHEMA";

mysql_declare_plugin(perfschema)
{
  MYSQL_STORAGE_ENGINE_PLUGIN,
  &pfs_storage_engine,
  pfs_engine_name,
  "Marc Alff, Oracle", /* Formerly Sun Microsystems, formerly MySQL */
  "Performance Schema",
  PLUGIN_LICENSE_GPL,
  pfs_init_func,                                /* Plugin Init */
  pfs_done_func,                                /* Plugin Deinit */
  0x0001 /* 0.1 */,
  pfs_status_vars,                              /* status variables */
  NULL,                                         /* system variables */
  NULL                                          /* config options */
}
mysql_declare_plugin_end;

ha_perfschema::ha_perfschema(handlerton *hton, TABLE_SHARE *share)
  : handler(hton, share), m_table_share(NULL), m_table(NULL)
{}

ha_perfschema::~ha_perfschema()
{}

static const char *ha_pfs_exts[]= {
  NullS
};

const char **ha_perfschema::bas_ext() const
{
  return ha_pfs_exts;
}

int ha_perfschema::open(const char *name, int mode, uint test_if_locked)
{
  DBUG_ENTER("ha_perfschema::open");

  m_table_share= find_table_share(table_share->db.str,
                                  table_share->table_name.str);
  if (! m_table_share)
    DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);

  thr_lock_data_init(m_table_share->m_thr_lock_ptr, &m_thr_lock, NULL);
  ref_length= m_table_share->m_ref_length;

  psi_open();

  DBUG_RETURN(0);
}

int ha_perfschema::close(void)
{
  DBUG_ENTER("ha_perfschema::close");
  m_table_share= NULL;
  delete m_table;
  m_table= NULL;

  psi_close();

  DBUG_RETURN(0);
}

int ha_perfschema::write_row(uchar *buf)
{
  int result;

  DBUG_ENTER("ha_perfschema::write_row");

  ha_statistic_increment(&SSV::ha_write_count);
  DBUG_ASSERT(m_table_share);

  if (m_table_share->m_write_row)
    result= m_table_share->m_write_row(table, buf, table->field);
  else
  {
    my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
    result= HA_ERR_WRONG_COMMAND;
  }

  DBUG_RETURN(result);
}

void ha_perfschema::use_hidden_primary_key(void)
{
  /*
    This is also called in case of row based replication,
    see TABLE::mark_columns_needed_for_update().
    Add all columns to the read set, but do not touch the write set,
    as some columns in the SETUP_ tables are not writable.
  */
  table->column_bitmaps_set_no_signal(&table->s->all_set, table->write_set);
}

int ha_perfschema::update_row(const uchar *old_data, uchar *new_data)
{
  DBUG_ENTER("ha_perfschema::update_row");

  DBUG_ASSERT(m_table);
  int result= m_table->update_row(table, old_data, new_data, table->field);
  DBUG_RETURN(result);
}

int ha_perfschema::rnd_init(bool scan)
{
  int result;
  DBUG_ENTER("ha_perfschema::rnd_init");

  DBUG_ASSERT(m_table_share);
  DBUG_ASSERT(m_table_share->m_open_table != NULL);

  stats.records= 0;
  if (m_table == NULL)
    m_table= m_table_share->m_open_table();
  else
    m_table->reset_position();

  result= m_table ? 0 : HA_ERR_OUT_OF_MEM;
  DBUG_RETURN(result);
}

int ha_perfschema::rnd_end(void)
{
  DBUG_ENTER("ha_perfschema::rnd_end");
  DBUG_ASSERT(m_table);
  delete m_table;
  m_table= NULL;
  DBUG_RETURN(0);
}

int ha_perfschema::rnd_next(uchar *buf)
{
  DBUG_ENTER("ha_perfschema::rnd_next");

  DBUG_ASSERT(m_table);
  int result= m_table->rnd_next();
  if (result == 0)
  {
    result= m_table->read_row(table, buf, table->field);
    if (result == 0)
      stats.records++;
  }
  DBUG_RETURN(result);
}

void ha_perfschema::position(const uchar *record)
{
  DBUG_ENTER("ha_perfschema::position");

  DBUG_ASSERT(m_table);
  m_table->get_position(ref);
  DBUG_VOID_RETURN;
}

int ha_perfschema::rnd_pos(uchar *buf, uchar *pos)
{
  DBUG_ENTER("ha_perfschema::rnd_pos");

  DBUG_ASSERT(m_table);
  int result= m_table->rnd_pos(pos);
  if (result == 0)
    result= m_table->read_row(table, buf, table->field);
  DBUG_RETURN(result);
}

int ha_perfschema::info(uint flag)
{
  DBUG_ENTER("ha_perfschema::info");
  DBUG_ASSERT(m_table_share);
  if (flag & HA_STATUS_VARIABLE)
    stats.records= m_table_share->m_records;
  if (flag & HA_STATUS_CONST)
    ref_length= m_table_share->m_ref_length;
  DBUG_RETURN(0);
}

int ha_perfschema::delete_all_rows(void)
{
  int result;

  DBUG_ENTER("ha_perfschema::delete_all_rows");

  DBUG_ASSERT(m_table_share);
  if (m_table_share->m_delete_all_rows)
    result= m_table_share->m_delete_all_rows();
  else
  {
    my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
    result= HA_ERR_WRONG_COMMAND;
  }
  DBUG_RETURN(result);
}

THR_LOCK_DATA **ha_perfschema::store_lock(THD *thd,
                                       THR_LOCK_DATA **to,
                                       enum thr_lock_type lock_type)
{
  if (lock_type != TL_IGNORE && m_thr_lock.type == TL_UNLOCK)
    m_thr_lock.type= lock_type;
  *to++= &m_thr_lock;
  m_thr_lock.m_psi= m_psi;
  return to;
}

int ha_perfschema::delete_table(const char *name)
{
  DBUG_ENTER("ha_perfschema::delete_table");
  DBUG_RETURN(0);
}

int ha_perfschema::rename_table(const char * from, const char * to)
{
  DBUG_ENTER("ha_perfschema::rename_table ");
  my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}

int ha_perfschema::create(const char *name, TABLE *table_arg,
                          HA_CREATE_INFO *create_info)
{
  DBUG_ENTER("ha_perfschema::create");
  DBUG_ASSERT(table_arg);
  DBUG_ASSERT(table_arg->s);
  if (find_table_share(table_arg->s->db.str,
                       table_arg->s->table_name.str))
  {
    /*
      Attempting to create a known performance schema table.
      Allowing the create, to create .FRM files,
      for the initial database install, and mysql_upgrade.
      This should fail once .FRM are removed.
    */
    DBUG_RETURN(0);
  }
  /*
    This is not a general purpose engine.
    Failure to CREATE TABLE is the expected result.
  */
  my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}

<commit_msg>Bug#56521 Assertion failed: (m_state == 2), function allocated_to_free, pfs_lock.h (138)<commit_after>/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; version 2 of the License.

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

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software Foundation,
  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */

/**
  @file storage/perfschema/ha_perfschema.cc
  Performance schema storage engine (implementation).
*/

#include "my_global.h"
#include "my_atomic.h"
#include "my_pthread.h"
#include "sql_plugin.h"
#include "mysql/plugin.h"
#include "ha_perfschema.h"
#include "pfs_engine_table.h"
#include "pfs_column_values.h"
#include "pfs_instr_class.h"
#include "pfs_instr.h"

#ifdef MY_ATOMIC_MODE_DUMMY
/*
  The performance schema can can not function with MY_ATOMIC_MODE_DUMMY,
  a fully functional implementation of MY_ATOMIC should be used instead.
  If the build fails with this error message:
  - either use a different ./configure --with-atomic-ops option
  - or do not build with the performance schema.
*/
#error "The performance schema needs a functional MY_ATOMIC implementation."
#endif

handlerton *pfs_hton= NULL;

static handler* pfs_create_handler(handlerton *hton,
                                   TABLE_SHARE *table,
                                   MEM_ROOT *mem_root)
{
  return new (mem_root) ha_perfschema(hton, table);
}

static int compare_database_names(const char *name1, const char *name2)
{
  if (lower_case_table_names)
    return strcasecmp(name1, name2);
  return strcmp(name1, name2);
}

static const PFS_engine_table_share*
find_table_share(const char *db, const char *name)
{
  DBUG_ENTER("find_table_share");

  if (compare_database_names(db, PERFORMANCE_SCHEMA_str.str) != 0)
    DBUG_RETURN(NULL);

  const PFS_engine_table_share* result;
  result= PFS_engine_table::find_engine_table_share(name);
  DBUG_RETURN(result);
}

static int pfs_init_func(void *p)
{
  DBUG_ENTER("pfs_init_func");

  pfs_hton= reinterpret_cast<handlerton *> (p);

  pfs_hton->state= SHOW_OPTION_YES;
  pfs_hton->create= pfs_create_handler;
  pfs_hton->show_status= pfs_show_status;
  pfs_hton->flags= HTON_ALTER_NOT_SUPPORTED |
    HTON_TEMPORARY_NOT_SUPPORTED |
    HTON_NO_PARTITION;

  /*
    As long as the server implementation keeps using legacy_db_type,
    as for example in mysql_truncate(),
    we can not rely on the fact that different mysqld process will assign
    consistently the same legacy_db_type for a given storage engine name.
    In particular, using different --loose-skip-xxx options between
    ./mysqld --bootstrap
    ./mysqld
    creates bogus .frm forms when bootstrapping the performance schema,
    if we rely on ha_initialize_handlerton to assign a really dynamic value.
    To fix this, a dedicated DB_TYPE is officially assigned to
    the performance schema. See Bug#43039.
  */
  pfs_hton->db_type= DB_TYPE_PERFORMANCE_SCHEMA;

  PFS_engine_table_share::init_all_locks();

  DBUG_RETURN(0);
}

static int pfs_done_func(void *p)
{
  DBUG_ENTER("pfs_done_func");

  pfs_hton= NULL;

  PFS_engine_table_share::delete_all_locks();

  DBUG_RETURN(0);
}

static struct st_mysql_show_var pfs_status_vars[]=
{
  {"Performance_schema_mutex_classes_lost",
    (char*) &mutex_class_lost, SHOW_LONG_NOFLUSH},
  {"Performance_schema_rwlock_classes_lost",
    (char*) &rwlock_class_lost, SHOW_LONG_NOFLUSH},
  {"Performance_schema_cond_classes_lost",
    (char*) &cond_class_lost, SHOW_LONG_NOFLUSH},
  {"Performance_schema_thread_classes_lost",
    (char*) &thread_class_lost, SHOW_LONG_NOFLUSH},
  {"Performance_schema_file_classes_lost",
    (char*) &file_class_lost, SHOW_LONG_NOFLUSH},
  {"Performance_schema_mutex_instances_lost",
    (char*) &mutex_lost, SHOW_LONG},
  {"Performance_schema_rwlock_instances_lost",
    (char*) &rwlock_lost, SHOW_LONG},
  {"Performance_schema_cond_instances_lost",
    (char*) &cond_lost, SHOW_LONG},
  {"Performance_schema_thread_instances_lost",
    (char*) &thread_lost, SHOW_LONG},
  {"Performance_schema_file_instances_lost",
    (char*) &file_lost, SHOW_LONG},
  {"Performance_schema_file_handles_lost",
    (char*) &file_handle_lost, SHOW_LONG},
  {"Performance_schema_locker_lost",
    (char*) &locker_lost, SHOW_LONG},
  /* table shares, can be flushed */
  {"Performance_schema_table_instances_lost",
    (char*) &table_share_lost, SHOW_LONG},
  /* table handles, can be flushed */
  {"Performance_schema_table_handles_lost",
    (char*) &table_lost, SHOW_LONG},
  {NullS, NullS, SHOW_LONG}
};

struct st_mysql_storage_engine pfs_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };

const char* pfs_engine_name= "PERFORMANCE_SCHEMA";

mysql_declare_plugin(perfschema)
{
  MYSQL_STORAGE_ENGINE_PLUGIN,
  &pfs_storage_engine,
  pfs_engine_name,
  "Marc Alff, Oracle", /* Formerly Sun Microsystems, formerly MySQL */
  "Performance Schema",
  PLUGIN_LICENSE_GPL,
  pfs_init_func,                                /* Plugin Init */
  pfs_done_func,                                /* Plugin Deinit */
  0x0001 /* 0.1 */,
  pfs_status_vars,                              /* status variables */
  NULL,                                         /* system variables */
  NULL                                          /* config options */
}
mysql_declare_plugin_end;

ha_perfschema::ha_perfschema(handlerton *hton, TABLE_SHARE *share)
  : handler(hton, share), m_table_share(NULL), m_table(NULL)
{}

ha_perfschema::~ha_perfschema()
{}

static const char *ha_pfs_exts[]= {
  NullS
};

const char **ha_perfschema::bas_ext() const
{
  return ha_pfs_exts;
}

int ha_perfschema::open(const char *name, int mode, uint test_if_locked)
{
  DBUG_ENTER("ha_perfschema::open");

  m_table_share= find_table_share(table_share->db.str,
                                  table_share->table_name.str);
  if (! m_table_share)
    DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);

  thr_lock_data_init(m_table_share->m_thr_lock_ptr, &m_thr_lock, NULL);
  ref_length= m_table_share->m_ref_length;

  psi_open();

  DBUG_RETURN(0);
}

int ha_perfschema::close(void)
{
  DBUG_ENTER("ha_perfschema::close");
  m_table_share= NULL;
  delete m_table;
  m_table= NULL;

  psi_close();

  DBUG_RETURN(0);
}

int ha_perfschema::write_row(uchar *buf)
{
  int result;

  DBUG_ENTER("ha_perfschema::write_row");

  ha_statistic_increment(&SSV::ha_write_count);
  DBUG_ASSERT(m_table_share);

  if (m_table_share->m_write_row)
    result= m_table_share->m_write_row(table, buf, table->field);
  else
  {
    my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
    result= HA_ERR_WRONG_COMMAND;
  }

  DBUG_RETURN(result);
}

void ha_perfschema::use_hidden_primary_key(void)
{
  /*
    This is also called in case of row based replication,
    see TABLE::mark_columns_needed_for_update().
    Add all columns to the read set, but do not touch the write set,
    as some columns in the SETUP_ tables are not writable.
  */
  table->column_bitmaps_set_no_signal(&table->s->all_set, table->write_set);
}

int ha_perfschema::update_row(const uchar *old_data, uchar *new_data)
{
  DBUG_ENTER("ha_perfschema::update_row");

  DBUG_ASSERT(m_table);
  int result= m_table->update_row(table, old_data, new_data, table->field);
  DBUG_RETURN(result);
}

int ha_perfschema::rnd_init(bool scan)
{
  int result;
  DBUG_ENTER("ha_perfschema::rnd_init");

  DBUG_ASSERT(m_table_share);
  DBUG_ASSERT(m_table_share->m_open_table != NULL);

  stats.records= 0;
  if (m_table == NULL)
    m_table= m_table_share->m_open_table();
  else
    m_table->reset_position();

  result= m_table ? 0 : HA_ERR_OUT_OF_MEM;
  DBUG_RETURN(result);
}

int ha_perfschema::rnd_end(void)
{
  DBUG_ENTER("ha_perfschema::rnd_end");
  DBUG_ASSERT(m_table);
  delete m_table;
  m_table= NULL;
  DBUG_RETURN(0);
}

int ha_perfschema::rnd_next(uchar *buf)
{
  DBUG_ENTER("ha_perfschema::rnd_next");

  DBUG_ASSERT(m_table);
  int result= m_table->rnd_next();
  if (result == 0)
  {
    result= m_table->read_row(table, buf, table->field);
    if (result == 0)
      stats.records++;
  }
  DBUG_RETURN(result);
}

void ha_perfschema::position(const uchar *record)
{
  DBUG_ENTER("ha_perfschema::position");

  DBUG_ASSERT(m_table);
  m_table->get_position(ref);
  DBUG_VOID_RETURN;
}

int ha_perfschema::rnd_pos(uchar *buf, uchar *pos)
{
  DBUG_ENTER("ha_perfschema::rnd_pos");

  DBUG_ASSERT(m_table);
  int result= m_table->rnd_pos(pos);
  if (result == 0)
    result= m_table->read_row(table, buf, table->field);
  DBUG_RETURN(result);
}

int ha_perfschema::info(uint flag)
{
  DBUG_ENTER("ha_perfschema::info");
  DBUG_ASSERT(m_table_share);
  if (flag & HA_STATUS_VARIABLE)
    stats.records= m_table_share->m_records;
  if (flag & HA_STATUS_CONST)
    ref_length= m_table_share->m_ref_length;
  DBUG_RETURN(0);
}

int ha_perfschema::delete_all_rows(void)
{
  int result;

  DBUG_ENTER("ha_perfschema::delete_all_rows");

  DBUG_ASSERT(m_table_share);
  if (m_table_share->m_delete_all_rows)
    result= m_table_share->m_delete_all_rows();
  else
  {
    my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
    result= HA_ERR_WRONG_COMMAND;
  }
  DBUG_RETURN(result);
}

THR_LOCK_DATA **ha_perfschema::store_lock(THD *thd,
                                       THR_LOCK_DATA **to,
                                       enum thr_lock_type lock_type)
{
  if (lock_type != TL_IGNORE && m_thr_lock.type == TL_UNLOCK)
    m_thr_lock.type= lock_type;
  *to++= &m_thr_lock;
  m_thr_lock.m_psi= m_psi;
  return to;
}

int ha_perfschema::delete_table(const char *name)
{
  DBUG_ENTER("ha_perfschema::delete_table");
  DBUG_RETURN(0);
}

int ha_perfschema::rename_table(const char * from, const char * to)
{
  DBUG_ENTER("ha_perfschema::rename_table ");
  my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}

int ha_perfschema::create(const char *name, TABLE *table_arg,
                          HA_CREATE_INFO *create_info)
{
  DBUG_ENTER("ha_perfschema::create");
  DBUG_ASSERT(table_arg);
  DBUG_ASSERT(table_arg->s);
  if (find_table_share(table_arg->s->db.str,
                       table_arg->s->table_name.str))
  {
    /*
      Attempting to create a known performance schema table.
      Allowing the create, to create .FRM files,
      for the initial database install, and mysql_upgrade.
      This should fail once .FRM are removed.
    */
    DBUG_RETURN(0);
  }
  /*
    This is not a general purpose engine.
    Failure to CREATE TABLE is the expected result.
  */
  my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}

<|endoftext|>


<commit_before>//
// Copyright (C) 2007 SIPez LLC.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// Copyright (C) 2007 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// $$
///////////////////////////////////////////////////////////////////////////////

// Author: Alexander Chemeris <Alexander DOT Chemeris AT SIPez DOT com>

#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <sipxunit/TestUtilities.h>

#include <mp/MpOutputDeviceManager.h>
#include <mp/MpAudioBuf.h>
#include <mp/MpSineWaveGeneratorDeviceDriver.h>
#include <os/OsTask.h>
#include <os/OsEvent.h>

#define TEST_SAMPLES_PER_FRAME_SIZE   80
#define BUFFER_NUM                    500
#define TEST_SAMPLES_PER_SECOND       8000
#define TEST_SAMPLE_DATA_SIZE         (TEST_SAMPLES_PER_SECOND*1)
#define TEST_SAMPLE_DATA_MAGNITUDE    32000
#define TEST_SAMPLE_DATA_PERIOD       (1000000/60) //in microseconds 60 Hz

#define CREATE_TEST_RUNS_NUMBER              3
#define ENABLE_DISABLE_TEST_RUNS_NUMBER      5
#define ENABLE_DISABLE_FAST_TEST_RUNS_NUMBER 10
#define DIRECT_WRITE_TEST_RUNS_NUMBER        3
#define TICKER_TEST_WRITE_RUNS_NUMBER        3

#undef USE_TEST_DRIVER

#ifdef USE_TEST_DRIVER // USE_TEST_DRIVER [
#include <mp/MpodBufferRecorder.h>
#define OUTPUT_DRIVER MpodBufferRecorder
#define OUTPUT_DRIVER_CONSTRUCTOR_PARAMS "default", TEST_SAMPLE_DATA_SIZE*1000/TEST_SAMPLES_PER_SECOND

#elif defined(WIN32) // USE_TEST_DRIVER ][ WIN32
#include <mp/MpodWinMM.h>
#define OUTPUT_DRIVER MpodWinMM
#define OUTPUT_DRIVER_CONSTRUCTOR_PARAMS MpodWinMM::getDefaultDeviceName()

#elif defined(__pingtel_on_posix__) // WIN32 ][ __pingtel_on_posix__
#include <mp/MpodOSS.h>
#define OUTPUT_DRIVER MpodOSS
#define OUTPUT_DRIVER_CONSTRUCTOR_PARAMS "/dev/dsp"

#else // __pingtel_on_posix__ ]
#error Unknown platform!
#endif

//static MpAudioSample sampleData[TEST_SAMPLE_DATA_SIZE];
//static UtlBoolean sampleDataInitialized=FALSE;

static void calculateSampleData(int frequency,
                                MpAudioSample sampleData[],
                                int samplesPerFrame,
                                int samplesPerSecond)
{
   for (int i=0; i<TEST_SAMPLE_DATA_SIZE; i++)
   {
      sampleData[i] =
         MpSineWaveGeneratorDeviceDriver::calculateSample(0,
                                                          TEST_SAMPLE_DATA_MAGNITUDE,
                                                          1000000 / frequency,
                                                          i,
                                                          samplesPerFrame,
                                                          samplesPerSecond);
   }
}

/**
 * Unittest for MpOutputDeviceDriver
 */
class MpOutputDeviceDriverTest : public CppUnit::TestCase
{
   CPPUNIT_TEST_SUITE(MpOutputDeviceDriverTest);
   CPPUNIT_TEST(testCreate);
   CPPUNIT_TEST(testEnableDisable);
   CPPUNIT_TEST(testEnableDisableFast);
   CPPUNIT_TEST(testDirectWrite);
   CPPUNIT_TEST(testTickerNotification);
   CPPUNIT_TEST_SUITE_END();

public:

   void setUp()
   {
      // Create pool for data buffers
      mpPool = new MpBufPool(TEST_SAMPLES_PER_FRAME_SIZE * sizeof(MpAudioSample)
                             + MpArrayBuf::getHeaderSize(), BUFFER_NUM);
      CPPUNIT_ASSERT(mpPool != NULL);

      // Create pool for buffer headers
      mpHeadersPool = new MpBufPool(sizeof(MpAudioBuf), BUFFER_NUM);
      CPPUNIT_ASSERT(mpHeadersPool != NULL);

      // Set mpHeadersPool as default pool for audio and data pools.
      MpAudioBuf::smpDefaultPool = mpHeadersPool;
      MpDataBuf::smpDefaultPool = mpHeadersPool;
   }

   void tearDown()
   {
      if (mpPool != NULL)
      {
         delete mpPool;
      }
      if (mpHeadersPool != NULL)
      {
         delete mpHeadersPool;
      }
   }

   void testCreate()
   {
      for (int i=0; i<CREATE_TEST_RUNS_NUMBER; i++)
      {
         OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);

         CPPUNIT_ASSERT(!driver.isEnabled());
      }
   }

   void testEnableDisable()
   {
      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      CPPUNIT_ASSERT(!driver.isEnabled());

      for (int i=0; i<ENABLE_DISABLE_TEST_RUNS_NUMBER; i++)
      {
         driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);
         CPPUNIT_ASSERT(driver.isEnabled());

         OsTask::delay(50);

         driver.disableDevice();
         CPPUNIT_ASSERT(!driver.isEnabled());
      }
   }

   void testEnableDisableFast()
   {
      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      CPPUNIT_ASSERT(!driver.isEnabled());

      for (int i=0; i<ENABLE_DISABLE_FAST_TEST_RUNS_NUMBER; i++)
      {
         driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);
         CPPUNIT_ASSERT(driver.isEnabled());

         driver.disableDevice();
         CPPUNIT_ASSERT(!driver.isEnabled());
      }
   }

   void testDirectWrite()
   {
      MpAudioSample sampleData[TEST_SAMPLE_DATA_SIZE];
      calculateSampleData(440, sampleData, 80, 8000);

      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      CPPUNIT_ASSERT(!driver.isEnabled());

      for (int i=0; i<DIRECT_WRITE_TEST_RUNS_NUMBER; i++)
      {
         MpFrameTime frameTime=0;

         driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);
         CPPUNIT_ASSERT(driver.isEnabled());

         // Write some data to device.
         for (int frame=0; frame<TEST_SAMPLE_DATA_SIZE/TEST_SAMPLES_PER_FRAME_SIZE; frame++)
         {
            OsTask::delay(1000*TEST_SAMPLES_PER_FRAME_SIZE/TEST_SAMPLES_PER_SECOND);
            CPPUNIT_ASSERT_EQUAL(OS_SUCCESS,
                                 driver.pushFrame(TEST_SAMPLES_PER_FRAME_SIZE,
                                                  sampleData + TEST_SAMPLES_PER_FRAME_SIZE*frame,
                                                  frameTime));

            frameTime += TEST_SAMPLES_PER_FRAME_SIZE*1000/TEST_SAMPLES_PER_SECOND;
         }

         driver.disableDevice();
         CPPUNIT_ASSERT(!driver.isEnabled());
      }
   }

   void testTickerNotification()
   {
      OsEvent notificationEvent;
      int sampleRates[]={8000, 16000, 32000, 48000};
      int numRates = 4;
      MpAudioSample sampleData[TEST_SAMPLE_DATA_SIZE];
      int frequencies[] = {1000, 2000, 4000, 8000, 16000, 20000};
      int numFreqs = 6;

      int rateIndex = 0;

      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      CPPUNIT_ASSERT(!driver.isEnabled());

      for (int i=0; i<numFreqs; i++)
      {
         printf("Frequency: %d (Hz) Sample rate: %d/sec.\n",
            frequencies[i], sampleRates[rateIndex]);
         calculateSampleData(frequencies[i], sampleData, sampleRates[rateIndex]/100, sampleRates[rateIndex]);
         MpFrameTime frameTime=0;

         driver.enableDevice(sampleRates[rateIndex]/100, sampleRates[rateIndex], 0);
         CPPUNIT_ASSERT(driver.isEnabled());

         CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, driver.setTickerNotification(&notificationEvent));

         // Write some data to device.
         for (int frame=0; frame<100; frame++)
         {
            CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, notificationEvent.wait(OsTime(1000)));
            notificationEvent.reset();
            CPPUNIT_ASSERT_EQUAL(OS_SUCCESS,
                                 driver.pushFrame(sampleRates[rateIndex]/100,
                                                  sampleData + sampleRates[rateIndex]/100*frame,
                                                  frameTime));

            frameTime += sampleRates[rateIndex]/100*1000/sampleRates[rateIndex];
         }

         CPPUNIT_ASSERT(driver.setTickerNotification(NULL) == OS_SUCCESS);

         driver.disableDevice();
         CPPUNIT_ASSERT(!driver.isEnabled());
      }
   }

protected:
   MpBufPool *mpPool;         ///< Pool for data buffers
   MpBufPool *mpHeadersPool;  ///< Pool for buffers headers

};

CPPUNIT_TEST_SUITE_REGISTRATION(MpOutputDeviceDriverTest);
<commit_msg>Bug fix: sampleData buffer size now adjusted properly for rate given.<commit_after>//
// Copyright (C) 2007 SIPez LLC.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// Copyright (C) 2007 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// $$
///////////////////////////////////////////////////////////////////////////////

// Author: Alexander Chemeris <Alexander DOT Chemeris AT SIPez DOT com>

#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <sipxunit/TestUtilities.h>

#include <mp/MpOutputDeviceManager.h>
#include <mp/MpAudioBuf.h>
#include <mp/MpSineWaveGeneratorDeviceDriver.h>
#include <os/OsTask.h>
#include <os/OsEvent.h>

#define TEST_SAMPLES_PER_FRAME_SIZE   80
#define BUFFER_NUM                    500
#define TEST_SAMPLES_PER_SECOND       8000
#define TEST_SAMPLE_DATA_SIZE         (TEST_SAMPLES_PER_SECOND*1)
#define TEST_SAMPLE_DATA_MAGNITUDE    32000
#define TEST_SAMPLE_DATA_PERIOD       (1000000/60) //in microseconds 60 Hz

#define CREATE_TEST_RUNS_NUMBER              3
#define ENABLE_DISABLE_TEST_RUNS_NUMBER      5
#define ENABLE_DISABLE_FAST_TEST_RUNS_NUMBER 10
#define DIRECT_WRITE_TEST_RUNS_NUMBER        3
#define TICKER_TEST_WRITE_RUNS_NUMBER        3

#undef USE_TEST_DRIVER

#ifdef USE_TEST_DRIVER // USE_TEST_DRIVER [
#include <mp/MpodBufferRecorder.h>
#define OUTPUT_DRIVER MpodBufferRecorder
#define OUTPUT_DRIVER_CONSTRUCTOR_PARAMS "default", TEST_SAMPLE_DATA_SIZE*1000/TEST_SAMPLES_PER_SECOND

#elif defined(WIN32) // USE_TEST_DRIVER ][ WIN32
#include <mp/MpodWinMM.h>
#define OUTPUT_DRIVER MpodWinMM
#define OUTPUT_DRIVER_CONSTRUCTOR_PARAMS MpodWinMM::getDefaultDeviceName()

#elif defined(__pingtel_on_posix__) // WIN32 ][ __pingtel_on_posix__
#include <mp/MpodOSS.h>
#define OUTPUT_DRIVER MpodOSS
#define OUTPUT_DRIVER_CONSTRUCTOR_PARAMS "/dev/dsp"

#else // __pingtel_on_posix__ ]
#error Unknown platform!
#endif

//static MpAudioSample sampleData[TEST_SAMPLE_DATA_SIZE];
//static UtlBoolean sampleDataInitialized=FALSE;

static void calculateSampleData(int frequency,
                                MpAudioSample sampleData[],
                                int samplesPerFrame,
                                int samplesPerSecond)
{
   for (int i=0; i<TEST_SAMPLE_DATA_SIZE; i++)
   {
      sampleData[i] =
         MpSineWaveGeneratorDeviceDriver::calculateSample(0,
                                                          TEST_SAMPLE_DATA_MAGNITUDE,
                                                          1000000 / frequency,
                                                          i,
                                                          samplesPerFrame,
                                                          samplesPerSecond);
   }
}

/**
 * Unittest for MpOutputDeviceDriver
 */
class MpOutputDeviceDriverTest : public CppUnit::TestCase
{
   CPPUNIT_TEST_SUITE(MpOutputDeviceDriverTest);
   CPPUNIT_TEST(testCreate);
   CPPUNIT_TEST(testEnableDisable);
   CPPUNIT_TEST(testEnableDisableFast);
   CPPUNIT_TEST(testDirectWrite);
   CPPUNIT_TEST(testTickerNotification);
   CPPUNIT_TEST_SUITE_END();

public:

   void setUp()
   {
      // Create pool for data buffers
      mpPool = new MpBufPool(TEST_SAMPLES_PER_FRAME_SIZE * sizeof(MpAudioSample)
                             + MpArrayBuf::getHeaderSize(), BUFFER_NUM);
      CPPUNIT_ASSERT(mpPool != NULL);

      // Create pool for buffer headers
      mpHeadersPool = new MpBufPool(sizeof(MpAudioBuf), BUFFER_NUM);
      CPPUNIT_ASSERT(mpHeadersPool != NULL);

      // Set mpHeadersPool as default pool for audio and data pools.
      MpAudioBuf::smpDefaultPool = mpHeadersPool;
      MpDataBuf::smpDefaultPool = mpHeadersPool;
   }

   void tearDown()
   {
      if (mpPool != NULL)
      {
         delete mpPool;
      }
      if (mpHeadersPool != NULL)
      {
         delete mpHeadersPool;
      }
   }

   void testCreate()
   {
      for (int i=0; i<CREATE_TEST_RUNS_NUMBER; i++)
      {
         OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);

         CPPUNIT_ASSERT(!driver.isEnabled());
      }
   }

   void testEnableDisable()
   {
      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      CPPUNIT_ASSERT(!driver.isEnabled());

      for (int i=0; i<ENABLE_DISABLE_TEST_RUNS_NUMBER; i++)
      {
         driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);
         CPPUNIT_ASSERT(driver.isEnabled());

         OsTask::delay(50);

         driver.disableDevice();
         CPPUNIT_ASSERT(!driver.isEnabled());
      }
   }

   void testEnableDisableFast()
   {
      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      CPPUNIT_ASSERT(!driver.isEnabled());

      for (int i=0; i<ENABLE_DISABLE_FAST_TEST_RUNS_NUMBER; i++)
      {
         driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);
         CPPUNIT_ASSERT(driver.isEnabled());

         driver.disableDevice();
         CPPUNIT_ASSERT(!driver.isEnabled());
      }
   }

   void testDirectWrite()
   {
      MpAudioSample sampleData[TEST_SAMPLE_DATA_SIZE];
      calculateSampleData(440, sampleData, 80, 8000);

      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      CPPUNIT_ASSERT(!driver.isEnabled());

      for (int i=0; i<DIRECT_WRITE_TEST_RUNS_NUMBER; i++)
      {
         MpFrameTime frameTime=0;

         driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);
         CPPUNIT_ASSERT(driver.isEnabled());

         // Write some data to device.
         for (int frame=0; frame<TEST_SAMPLE_DATA_SIZE/TEST_SAMPLES_PER_FRAME_SIZE; frame++)
         {
            OsTask::delay(1000*TEST_SAMPLES_PER_FRAME_SIZE/TEST_SAMPLES_PER_SECOND);
            CPPUNIT_ASSERT_EQUAL(OS_SUCCESS,
                                 driver.pushFrame(TEST_SAMPLES_PER_FRAME_SIZE,
                                                  sampleData + TEST_SAMPLES_PER_FRAME_SIZE*frame,
                                                  frameTime));

            frameTime += TEST_SAMPLES_PER_FRAME_SIZE*1000/TEST_SAMPLES_PER_SECOND;
         }

         driver.disableDevice();
         CPPUNIT_ASSERT(!driver.isEnabled());
      }
   }

   void testTickerNotification()
   {
      OsEvent notificationEvent;
      int sampleRates[]={8000, 16000, 32000, 48000};
      int numRates = 4;
      int frequencies[] = {1000, 2000, 4000, 8000, 16000, 20000};
      int numFreqs = 6;

      int rateIndex = 0;
      MpAudioSample* sampleData = new MpAudioSample[sampleRates[rateIndex]];

      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      CPPUNIT_ASSERT(!driver.isEnabled());

      for (int i=0; i<numFreqs; i++)
      {
         printf("Frequency: %d (Hz) Sample rate: %d/sec.\n",
            frequencies[i], sampleRates[rateIndex]);
         calculateSampleData(frequencies[i], sampleData, sampleRates[rateIndex]/100, sampleRates[rateIndex]);
         MpFrameTime frameTime=0;

         driver.enableDevice(sampleRates[rateIndex]/100, sampleRates[rateIndex], 0);
         CPPUNIT_ASSERT(driver.isEnabled());

         CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, driver.setTickerNotification(&notificationEvent));

         // Write some data to device.
         for (int frame=0; frame<100; frame++)
         {
            CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, notificationEvent.wait(OsTime(1000)));
            notificationEvent.reset();
            CPPUNIT_ASSERT_EQUAL(OS_SUCCESS,
                                 driver.pushFrame(sampleRates[rateIndex]/100,
                                                  sampleData + sampleRates[rateIndex]/100*frame,
                                                  frameTime));

            frameTime += sampleRates[rateIndex]/100*1000/sampleRates[rateIndex];
         }

         CPPUNIT_ASSERT(driver.setTickerNotification(NULL) == OS_SUCCESS);

         driver.disableDevice();
         CPPUNIT_ASSERT(!driver.isEnabled());
      }
      delete[] sampleData;
   }

protected:
   MpBufPool *mpPool;         ///< Pool for data buffers
   MpBufPool *mpHeadersPool;  ///< Pool for buffers headers

};

CPPUNIT_TEST_SUITE_REGISTRATION(MpOutputDeviceDriverTest);
<|endoftext|>


<commit_before>#include "datalayer.h"
#include "persons.h"

#include <string>
#include <vector>
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

DataLayer::DataLayer()
{
    loadFromFile();
}
vector<Persons> DataLayer::getVector()
{
    vector<Persons> myV;

    for(int i = 0; i < people.size();i++)
    {
       // vector<Persons> myV = people;
        myV.push_back(people[i]);

    }
       return myV;
}

void DataLayer::loadFromFile()
{

    Persons p;
    ifstream inStream;

    inStream.open("textFile.txt");

    while(inStream >> p)
    {

        people.push_back(p);
        cout << p;

        addPerson(p);

    }
    inStream.close();

    }

void DataLayer::saveToFile()
{
    fstream out;

    out.open("textFile.txt");

    for (size_t i = 0; i < people.size(); i++)
    {
        out << people[i] << endl;
    }

    out.close();
}

void DataLayer::addPerson(const Persons& p) {
    people.push_back(p);
}

void DataLayer::listPersons()
{

}

void DataLayer::sortByName()
{

}

void DataLayer::sortByBirthYear()
{
    int i = 0, j = people.size();
    Persons tmp;
    int pivot = people[people.size() / 2].getBirthYear();

  while (i <= j)
  {
        while (people[i].getBirthYear() < pivot)
        {
              i++;
        }
        while (people[j].getBirthYear() > pivot)
        {
              j--;
        }
        if (i <= j)
        {
              tmp = people[i];
              people[i] = people[j];
              people[j] = tmp;
              i++;
              j--;
        }
  }
}

void DataLayer::sortByDeathYear()
{
    int i = 0, j = people.size();
    Persons tmp;
    int pivot = people[people.size() / 2].getDeathYear();

    while (i <= j)
    {
        while (people[i].getDeathYear() < pivot)
        {
              i++;
        }
        while (people[j].getDeathYear() > pivot)
        {
              j--;
        }
        if (i <= j)
        {
              tmp = people[i];
              people[i] = people[j];
              people[j] = tmp;
              i++;
              j--;
        }
    }
}

void DataLayer::sortByGender()
{

}
<commit_msg>breytti int í size_t<commit_after>#include "datalayer.h"
#include "persons.h"

#include <string>
#include <vector>
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

DataLayer::DataLayer()
{
    loadFromFile();
}
vector<Persons> DataLayer::getVector()
{
    vector<Persons> myV;

    for(size_t i = 0; i < people.size();i++)
    {
       // vector<Persons> myV = people;
        myV.push_back(people[i]);

    }
       return myV;
}

void DataLayer::loadFromFile()
{

    Persons p;
    ifstream inStream;

    inStream.open("textFile.txt");

    while(inStream >> p)
    {

        people.push_back(p);
        cout << p;

        addPerson(p);

    }
    inStream.close();

    }

void DataLayer::saveToFile()
{
    fstream out;

    out.open("textFile.txt");

    for (size_t i = 0; i < people.size(); i++)
    {
        out << people[i] << endl;
    }

    out.close();
}

void DataLayer::addPerson(const Persons& p) {
    people.push_back(p);
}

void DataLayer::listPersons()
{

}

void DataLayer::sortByName()
{

}

void DataLayer::sortByBirthYear()
{
    int i = 0, j = people.size();
    Persons tmp;
    int pivot = people[people.size() / 2].getBirthYear();

  while (i <= j)
  {
        while (people[i].getBirthYear() < pivot)
        {
              i++;
        }
        while (people[j].getBirthYear() > pivot)
        {
              j--;
        }
        if (i <= j)
        {
              tmp = people[i];
              people[i] = people[j];
              people[j] = tmp;
              i++;
              j--;
        }
  }
}

void DataLayer::sortByDeathYear()
{
    int i = 0, j = people.size();
    Persons tmp;
    int pivot = people[people.size() / 2].getDeathYear();

    while (i <= j)
    {
        while (people[i].getDeathYear() < pivot)
        {
              i++;
        }
        while (people[j].getDeathYear() > pivot)
        {
              j--;
        }
        if (i <= j)
        {
              tmp = people[i];
              people[i] = people[j];
              people[j] = tmp;
              i++;
              j--;
        }
    }
}

void DataLayer::sortByGender()
{

}
<|endoftext|>


<commit_before>/*
    open source routing machine
    Copyright (C) Dennis Luxen, others 2010

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.

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

You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
or see http://www.gnu.org/licenses/agpl.txt.
 */

#include <cassert>
#include <climits>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <libxml/xmlreader.h>

#include <google/sparse_hash_map>

#include <stxxl/mng>
#include <stxxl/ksort>
#include <stxxl/sort>
#include <stxxl/vector>
#include <stxxl/bits/io/syscall_file.h>

#include "typedefs.h"
#include "DataStructures/extractorStructs.h"

using namespace std;
typedef google::dense_hash_map<NodeID, _Node> NodeMap;

_Stats stats;
Settings settings;
vector<NodeID> SignalNodes;

NodeMap * nodeMap = new NodeMap();

int main (int argc, char *argv[])
{
	if(argc <= 1)
	{
		cerr << "usage: " << endl << argv[0] << " <file.osm>" << endl;
		exit(-1);
	}
	cout << "reading input file. This may take some time ..." << flush;
	/*
     Default Speed Profile:
        motorway        120
        motorway_link   80
        trunk           100
        trunk_link      80
        secondary       100
        secondary_link  50
        primary         100
        primary_link    50
        tertiary        100
        unclassified    50
        residential     50
        living_street   30
        service         20
	 */
	double time = get_timestamp();
	string names[13] = { "motorway", "motorway_link", "trunk", "trunk_link", "secondary", "secondary_link", "primary", "primary_link", "tertiary", "unclassified", "residential", "living_street", "service" };
	double speeds[13] = { 120, 80, 100, 80, 100, 50, 100, 50, 100, 50, 50 , 30, 20};
	settings.speedProfile.names.insert(settings.speedProfile.names.begin(), names, names+13);
	settings.speedProfile.speed.insert(settings.speedProfile.speed.begin(), speeds, speeds+13);

	xmlTextReaderPtr inputReader = xmlNewTextReaderFilename( argv[1] );
	ofstream allNodeFile("_allnodes", ios::binary);
	ofstream usedNodesFile("_usednodes", ios::binary);
	ofstream wayFile("_ways", ios::binary);
	nodeMap->set_empty_key(UINT_MAX);
	try {
		while ( xmlTextReaderRead( inputReader ) == 1 ) {
			const int type = xmlTextReaderNodeType( inputReader );

			//1 is Element
			if ( type != 1 )
				continue;

			xmlChar* currentName = xmlTextReaderName( inputReader );
			if ( currentName == NULL )
				continue;

			if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
				stats.numberOfNodes++;
				_Node node = _ReadXMLNode( inputReader );
				allNodeFile.write((char *)&node, sizeof(node));// << node.id << node.lat << node.lon << node.trafficSignal << endl;

				if ( node.trafficSignal )
					SignalNodes.push_back( node.id );

			}
			else if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
				stats.numberOfWays++;
				_Way way = _ReadXMLWay( inputReader, settings, stats );

				if ( way.usefull && way.access && way.path.size() ) {
					for ( unsigned i = 0; i < way.path.size(); ++i ) {
						usedNodesFile.write((char *)&way.path[i], sizeof(NodeID));
					}

					if ( way.direction == _Way::opposite )
						std::reverse( way.path.begin(), way.path.end() );

					stats.numberOfEdges += ( int ) way.path.size() - 1;
					{
						vector< NodeID > & path = way.path;
						double speed = way.maximumSpeed;
						assert(way.type > -1 || way.maximumSpeed != -1);
						assert(path.size()>0);

						for(vector< NodeID >::size_type n = 0; n < path.size()-1; n++)
						{
							//serialize edge (path[n], path[n+1])
							wayFile.write((char*)&way.path[n], sizeof(NodeID));
							wayFile.write((char*)&way.path[n+1], sizeof(NodeID));
							wayFile.write((char*)&way.type, sizeof(short));
							wayFile.write((char*)&way.direction, sizeof(short));
							wayFile.write((char*)&way.maximumSpeed, sizeof(double));
						}
					}
				}
			}
			xmlFree( currentName );
		}
		allNodeFile.close();
		usedNodesFile.close();
		wayFile.close();
		cout << "ok, after " << get_timestamp() - time << "s" << endl;
		time = get_timestamp();
		unsigned memory_to_use = 1024 * 1024 * 1024;

		stxxl::syscall_file f("_usednodes", stxxl::file::DIRECT | stxxl::file::RDWR);
		typedef stxxl::vector<NodeID> usedNodesVectorType;

		usedNodesVectorType usedNodes( &f);
		cout << "Sorting used nodes ..." << flush;
		stxxl::sort(usedNodes.begin(), usedNodes.end(), Cmp(), memory_to_use);
		cout << "ok, after " << get_timestamp() - time << "s" << endl;
		time = get_timestamp();
		cout << "Erasing duplicate entries ..." << flush;
		stxxl::vector<NodeID>::iterator NewEnd = unique ( usedNodes.begin(),usedNodes.end() ) ;
		usedNodes.resize ( NewEnd - usedNodes.begin() );
		cout << "ok, after " << get_timestamp() - time << "s" << endl;
		time = get_timestamp();

		stxxl::syscall_file fallnodes("_allnodes", stxxl::file::DIRECT | stxxl::file::RDWR);
		typedef stxxl::vector< _Node > second_vector_type;

		second_vector_type van(&fallnodes);
		cout << "Sorting all nodes ..." << flush;
		stxxl::ksort(van.begin(), van.end(), memory_to_use);
		cout << "ok, after " << get_timestamp() - time << "s" << endl;
		time = get_timestamp();

		cout << endl << "Statistics: " << endl;
		cout << "All Nodes: " << stats.numberOfNodes << endl;
		cout << "Used Nodes: " << nodeMap->size() << endl;
		cout << "Number of Ways: " << stats.numberOfWays << endl;
		cout << "Edges in graph: " << stats.numberOfEdges << endl;
		cout << "Number of ways with maxspeed information: " << stats.numberOfMaxspeed << endl;
		cout << "Number of nodes with traffic lights: " << SignalNodes.size() << endl;
		cout << "finished loading data" << endl;
		cout << "calculated edge weights and writing to disk ..." << flush;
		string name(argv[1]);
		int pos=name.find(".osm"); // pos=9
		if(pos!=string::npos)
		{
			name.replace(pos, 5, ".osrm");
		} else {
			name.append(".osrm");
		}

		ofstream fout;
		fout.open(name.c_str());
		ifstream inall("_allnodes", ios::binary);
		ifstream inuse("_usednodes", ios::binary);
		ifstream inway("_ways", ios::binary);

		cout << "Writing used nodes ..." << flush;
		fout << usedNodes.size() << endl;
		NodeID counter = 0;
		for(usedNodesVectorType::iterator it = usedNodes.begin(); it!=usedNodes.end(); it++)
		{
			NodeID currentNodeID = *it;
			_Node current_Node;
			inall.read((char *)&current_Node, sizeof(_Node));
			while(currentNodeID!=current_Node.id)
			{
				inall.read((char *)&current_Node, sizeof(_Node));
			}
			fout << current_Node.id<< " " << current_Node.lon << " " << current_Node.lat << "\n";
			nodeMap->insert(std::make_pair(current_Node.id, current_Node));
			counter++;
		}
		cout << "ok, after " << get_timestamp() - time << "s" << endl;
		time = get_timestamp();

		cout << "writing used ways ..." << endl;
		NodeID start, target;
		short type, direction;
		double maximumSpeed;
		fout << stats.numberOfEdges << "\n";
		while(!inway.eof())
		{

			inway.read((char*)&start, sizeof(NodeID));
			inway.read((char*)&target, sizeof(NodeID));
			inway.read((char*)&type, sizeof(short));
			inway.read((char*)&direction, sizeof(short));
			inway.read((char*)&maximumSpeed, sizeof(double));
			assert(type > -1 || maximumSpeed != -1);

			NodeMap::iterator startit = nodeMap->find(start);
			if(startit == nodeMap->end())
			{
				cerr << "Node " << start << " missing albeit referenced in way. Edge skipped" << endl;
				continue;
			}
			NodeMap::iterator targetit = nodeMap->find(target);

			if(targetit == nodeMap->end())
			{
				cerr << "Node << " << target << "missing albeit reference in a way. Edge skipped" << endl;
				continue;
			}

			double distance = ApproximateDistance(startit->second.lat, startit->second.lon, targetit->second.lat, targetit->second.lon);
			if(maximumSpeed == -1)
				maximumSpeed = settings.speedProfile.speed[type];
			double weight = ( distance * 10. ) / (maximumSpeed / 3.6);
			double intWeight = max(1, (int) weight);
			switch(direction)
			{
			case _Way::notSure:
				fout << startit->first << " " << targetit->first << " " << max(1, (int)distance) << " " << 0 << " " << intWeight << "\n";
				break;
			case _Way::oneway:
				fout << startit->first << " " << targetit->first << " " << max(1, (int)distance) << " " << 1 << " " << intWeight << "\n";
				break;
			case _Way::bidirectional:
				fout << startit->first << " " << targetit->first << " " << max(1, (int)distance) << " " << 0 << " " << intWeight << "\n";
				break;
			case _Way::opposite:
				fout << startit->first << " " << targetit->first << " " << max(1, (int)distance) << " " << 1 << " " << intWeight << "\n";
				break;
			default:
				assert(false);
				break;
			}
		}
		inway.close();
		fout.close();
		cout << "ok, after " << get_timestamp() - time << "s" << endl;
		time = get_timestamp();
	} catch ( const std::exception& e ) {
		cerr <<  "Caught Execption:" << e.what() << endl;
		return false;
	}
	SignalNodes.clear();
	xmlFreeTextReader(inputReader);

	remove("_allnodes");
	remove("_usednodes");
	remove("_ways");
	return true;
}

<commit_msg>Replacing many includes by a single one<commit_after>/*
    open source routing machine
    Copyright (C) Dennis Luxen, others 2010

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.

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

You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
or see http://www.gnu.org/licenses/agpl.txt.
 */

#include <cassert>
#include <climits>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <libxml/xmlreader.h>

#include <google/sparse_hash_map>

#include <stxxl.h>

#include "typedefs.h"
#include "DataStructures/extractorStructs.h"

using namespace std;
typedef google::dense_hash_map<NodeID, _Node> NodeMap;

_Stats stats;
Settings settings;
vector<NodeID> SignalNodes;

NodeMap * nodeMap = new NodeMap();

int main (int argc, char *argv[])
{
	if(argc <= 1)
	{
		cerr << "usage: " << endl << argv[0] << " <file.osm>" << endl;
		exit(-1);
	}
	cout << "reading input file. This may take some time ..." << flush;
	/*
     Default Speed Profile:
        motorway        120
        motorway_link   80
        trunk           100
        trunk_link      80
        secondary       100
        secondary_link  50
        primary         100
        primary_link    50
        tertiary        100
        unclassified    50
        residential     50
        living_street   30
        service         20
	 */
	double time = get_timestamp();
	string names[13] = { "motorway", "motorway_link", "trunk", "trunk_link", "secondary", "secondary_link", "primary", "primary_link", "tertiary", "unclassified", "residential", "living_street", "service" };
	double speeds[13] = { 120, 80, 100, 80, 100, 50, 100, 50, 100, 50, 50 , 30, 20};
	settings.speedProfile.names.insert(settings.speedProfile.names.begin(), names, names+13);
	settings.speedProfile.speed.insert(settings.speedProfile.speed.begin(), speeds, speeds+13);

	xmlTextReaderPtr inputReader = xmlNewTextReaderFilename( argv[1] );
	ofstream allNodeFile("_allnodes", ios::binary);
	ofstream usedNodesFile("_usednodes", ios::binary);
	ofstream wayFile("_ways", ios::binary);
	nodeMap->set_empty_key(UINT_MAX);
	try {
		while ( xmlTextReaderRead( inputReader ) == 1 ) {
			const int type = xmlTextReaderNodeType( inputReader );

			//1 is Element
			if ( type != 1 )
				continue;

			xmlChar* currentName = xmlTextReaderName( inputReader );
			if ( currentName == NULL )
				continue;

			if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
				stats.numberOfNodes++;
				_Node node = _ReadXMLNode( inputReader );
				allNodeFile.write((char *)&node, sizeof(node));// << node.id << node.lat << node.lon << node.trafficSignal << endl;

				if ( node.trafficSignal )
					SignalNodes.push_back( node.id );

			}
			else if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
				stats.numberOfWays++;
				_Way way = _ReadXMLWay( inputReader, settings, stats );

				if ( way.usefull && way.access && way.path.size() ) {
					for ( unsigned i = 0; i < way.path.size(); ++i ) {
						usedNodesFile.write((char *)&way.path[i], sizeof(NodeID));
					}

					if ( way.direction == _Way::opposite )
						std::reverse( way.path.begin(), way.path.end() );

					stats.numberOfEdges += ( int ) way.path.size() - 1;
					{
						vector< NodeID > & path = way.path;
						double speed = way.maximumSpeed;
						assert(way.type > -1 || way.maximumSpeed != -1);
						assert(path.size()>0);

						for(vector< NodeID >::size_type n = 0; n < path.size()-1; n++)
						{
							//serialize edge (path[n], path[n+1])
							wayFile.write((char*)&way.path[n], sizeof(NodeID));
							wayFile.write((char*)&way.path[n+1], sizeof(NodeID));
							wayFile.write((char*)&way.type, sizeof(short));
							wayFile.write((char*)&way.direction, sizeof(short));
							wayFile.write((char*)&way.maximumSpeed, sizeof(double));
						}
					}
				}
			}
			xmlFree( currentName );
		}
		allNodeFile.close();
		usedNodesFile.close();
		wayFile.close();
		cout << "ok, after " << get_timestamp() - time << "s" << endl;
		time = get_timestamp();
		unsigned memory_to_use = 1024 * 1024 * 1024;

		stxxl::syscall_file f("_usednodes", stxxl::file::DIRECT | stxxl::file::RDWR);
		typedef stxxl::vector<NodeID> usedNodesVectorType;

		usedNodesVectorType usedNodes( &f);
		cout << "Sorting used nodes ..." << flush;
		stxxl::sort(usedNodes.begin(), usedNodes.end(), Cmp(), memory_to_use);
		cout << "ok, after " << get_timestamp() - time << "s" << endl;
		time = get_timestamp();
		cout << "Erasing duplicate entries ..." << flush;
		stxxl::vector<NodeID>::iterator NewEnd = unique ( usedNodes.begin(),usedNodes.end() ) ;
		usedNodes.resize ( NewEnd - usedNodes.begin() );
		cout << "ok, after " << get_timestamp() - time << "s" << endl;
		time = get_timestamp();

		stxxl::syscall_file fallnodes("_allnodes", stxxl::file::DIRECT | stxxl::file::RDWR);
		typedef stxxl::vector< _Node > second_vector_type;

		second_vector_type van(&fallnodes);
		cout << "Sorting all nodes ..." << flush;
		stxxl::ksort(van.begin(), van.end(), memory_to_use);
		cout << "ok, after " << get_timestamp() - time << "s" << endl;
		time = get_timestamp();

		cout << endl << "Statistics: " << endl;
		cout << "All Nodes: " << stats.numberOfNodes << endl;
		cout << "Used Nodes: " << nodeMap->size() << endl;
		cout << "Number of Ways: " << stats.numberOfWays << endl;
		cout << "Edges in graph: " << stats.numberOfEdges << endl;
		cout << "Number of ways with maxspeed information: " << stats.numberOfMaxspeed << endl;
		cout << "Number of nodes with traffic lights: " << SignalNodes.size() << endl;
		cout << "finished loading data" << endl;
		cout << "calculated edge weights and writing to disk ..." << flush;
		string name(argv[1]);
		int pos=name.find(".osm"); // pos=9
		if(pos!=string::npos)
		{
			name.replace(pos, 5, ".osrm");
		} else {
			name.append(".osrm");
		}

		ofstream fout;
		fout.open(name.c_str());
		ifstream inall("_allnodes", ios::binary);
		ifstream inuse("_usednodes", ios::binary);
		ifstream inway("_ways", ios::binary);

		cout << "Writing used nodes ..." << flush;
		fout << usedNodes.size() << endl;
		NodeID counter = 0;
		for(usedNodesVectorType::iterator it = usedNodes.begin(); it!=usedNodes.end(); it++)
		{
			NodeID currentNodeID = *it;
			_Node current_Node;
			inall.read((char *)&current_Node, sizeof(_Node));
			while(currentNodeID!=current_Node.id)
			{
				inall.read((char *)&current_Node, sizeof(_Node));
			}
			fout << current_Node.id<< " " << current_Node.lon << " " << current_Node.lat << "\n";
			nodeMap->insert(std::make_pair(current_Node.id, current_Node));
			counter++;
		}
		cout << "ok, after " << get_timestamp() - time << "s" << endl;
		time = get_timestamp();

		cout << "writing used ways ..." << endl;
		NodeID start, target;
		short type, direction;
		double maximumSpeed;
		fout << stats.numberOfEdges << "\n";
		while(!inway.eof())
		{

			inway.read((char*)&start, sizeof(NodeID));
			inway.read((char*)&target, sizeof(NodeID));
			inway.read((char*)&type, sizeof(short));
			inway.read((char*)&direction, sizeof(short));
			inway.read((char*)&maximumSpeed, sizeof(double));
			assert(type > -1 || maximumSpeed != -1);

			NodeMap::iterator startit = nodeMap->find(start);
			if(startit == nodeMap->end())
			{
				cerr << "Node " << start << " missing albeit referenced in way. Edge skipped" << endl;
				continue;
			}
			NodeMap::iterator targetit = nodeMap->find(target);

			if(targetit == nodeMap->end())
			{
				cerr << "Node << " << target << "missing albeit reference in a way. Edge skipped" << endl;
				continue;
			}

			double distance = ApproximateDistance(startit->second.lat, startit->second.lon, targetit->second.lat, targetit->second.lon);
			if(maximumSpeed == -1)
				maximumSpeed = settings.speedProfile.speed[type];
			double weight = ( distance * 10. ) / (maximumSpeed / 3.6);
			double intWeight = max(1, (int) weight);
			switch(direction)
			{
			case _Way::notSure:
				fout << startit->first << " " << targetit->first << " " << max(1, (int)distance) << " " << 0 << " " << intWeight << "\n";
				break;
			case _Way::oneway:
				fout << startit->first << " " << targetit->first << " " << max(1, (int)distance) << " " << 1 << " " << intWeight << "\n";
				break;
			case _Way::bidirectional:
				fout << startit->first << " " << targetit->first << " " << max(1, (int)distance) << " " << 0 << " " << intWeight << "\n";
				break;
			case _Way::opposite:
				fout << startit->first << " " << targetit->first << " " << max(1, (int)distance) << " " << 1 << " " << intWeight << "\n";
				break;
			default:
				assert(false);
				break;
			}
		}
		inway.close();
		fout.close();
		cout << "ok, after " << get_timestamp() - time << "s" << endl;
		time = get_timestamp();
	} catch ( const std::exception& e ) {
		cerr <<  "Caught Execption:" << e.what() << endl;
		return false;
	}
	SignalNodes.clear();
	xmlFreeTextReader(inputReader);

	remove("_allnodes");
	remove("_usednodes");
	remove("_ways");
	return true;
}

<|endoftext|>