<commit_before>
#pragma once

#include <functional>

#include "geometry/frame.hpp"
#include "geometry/named_quantities.hpp"
#include "quantities/si.hpp"
#include "serialization/geometry.pb.h"

namespace principia {
namespace astronomy {
namespace internal_frames {

using geometry::Frame;
using geometry::Instant;
using geometry::Position;
using quantities::si::ArcMinute;
using quantities::si::ArcSecond;
using quantities::si::Degree;

// The International Celestial Reference System.
// The origin is the barycentre of the solar system.  The axes are fixed with
// respect to the quasars.
// The xy plane is close to the mean equator at J2000.0.
// The x axis is close to the dynamical equinox at J2000.
// The z axis is perpendicular to the xy plane and points to the northern side
// of the xy plane.
// To be honest:
using ICRS = Frame<serialization::Frame::SolarSystemTag,
                   serialization::Frame::ICRS,
                   /*frame_is_inertial=*/true>;

// The Geocentric Celestial Reference System.
// The origin is the centre of mass of the whole Earth system, including oceans
// and atmosphere; the axes are those of the ICRS.
// To be honest:
// - The BCRS and GCRS are relativistic reference systems.
// - The transformation between BCRS and GCRS spatial coordinates has no
//   rotational component, i.e., the GCRS is kinematically non-rotating with
//   respect to the BCRS; as a result, it rotates dynamically with respect to
//   the BCRS; in particular, the equations of motion in the GCRS include de
//   Sitter and Lense–Thirring precession.
// - The time coordinate of the BCRS is TCB, and the time coordinate of the GCRS
//   is TCG; TT is a linear scaling of TCG, and TDB is a linear scaling of TDB;
//   for practical purposes TT and TDB are within 2 ms of each other;
//   Principia's |Instant| is TT.
using GCRS = Frame<serialization::Frame::SolarSystemTag,
                   serialization::Frame::GCRS,
                   /*frame_is_inertial=*/false>;

// The International Terrestrial Reference System.
// The origin is the centre of mass of the whole Earth system, including oceans
// and atmosphere; there is no global residual rotation with respect to
// horizontal motions at the earth's surface.
// Practical notes:
// - This is identical to WGS84 at 1 m level, and to recent realizations of WGS
//   84 at 10 cm level; the xz plane is a bit over a hundred metres from the
//   Royal Observatory in Greenwich.
//   Caveat: using |SphericalCoordinates<Length>| on ITRS coordinates is
//   inconsistent with WGS 84 latitudes; the WGS 84 geoid should be used.
// - The ITRS is related to the European Terrestrial Reference System (ETRS89)
//   by a time-dependent rigid transformation.
// To be honest:
// - There are many realizations of the ITRS; as of this writing, ICRFs 89, 90,
//   91, 92, 93, 94, 96, 97, 2000, 2005, 2008, and 2014.  They are related by
//   linearly time-dependent linearized similarity transformations with nonzero
//   scaling, which the current abstractions of Principia cannot support; see
//   Transformation parameters from ITRF2014 to past ITRFs,
//   http://itrf.ensg.ign.fr/doc_ITRF/Transfo-ITRF2014_ITRFs.txt.  Identifying
//   recent ITRFs (2005 and later) results in errors of a few millimetres at the
//   geocentre, scale errors on the order of 1 part-per-billion, and angular
//   errors below 1 μas.  Identifying earlier ITRFs results in errors may result
//   in errors of tens of centimetres at the geocentre, scale errors on the
//   order of ten parts per billion, and arcsecond-level angular errors.
// - ETRFyy is always related to the corresponding ITRFyy by a linearized rigid
//   transformation depending linearly on time, however it is related to other
//   ITRFs by time-dependent similarity with time-dependent nonzero scaling; see
//   the tables in EUREF Technical Note 1,
//   http://etrs89.ensg.ign.fr/pub/EUREF-TN-1.pdf
using ITRS = Frame<serialization::Frame::SolarSystemTag,
                   serialization::Frame::ITRS,
                   /*frame_is_inertial=*/false>;

// The following two reference systems are both geocentric, and they share the
// same z axis, the Celestial Intermediate Pole.  Their common xy plane is the
// intermediate equator.
// The rotation around the z axis relating the Terrestrial and Celestial
// Intermediate Reference Systems, i.e., the angle between the Terrestrial and
// Celestial Intermediate Origins, is the Earth Rotation Angle (ERA); the Earth
// Rotation Angle is an affine function of UT1 defined by equation 5.14 of the
// IERS conventions (2010).  Note that the rate is faster than 2π radians per
// UT1 day, as UT1 is notionally mean solar days, whereas revolutions of the ERA
// are stellar days.

// The glossary of the Nomenclature for Fundamental Astronomy notes for both
// that "since the acronym for this system is close to another acronym (namely
// [ITRS, respectively ICRS]), it is suggested that wherever possible the
// complete name be used".

// The Terrestrial Intermediate Reference System.
// The x axis is the Terrestrial Intermediate Origin.
// The ITRS is related to the Terrestrial Intermediate Reference System by polar
// motion, as described in sections 5.4.1 and 5.5.1 of the IERS conventions
// (2010).
// TODO(egg): identifying this with the ITRS, besides leading to acronym
// confusion, results in arcsecond-level errors.
using TerrestrialIntermediateReferenceSystem = ITRS;

// The origin is geocentric; the basis is right-handed and orthonormal, the xy
// plane is the same as that of the Terrestrial Intermediate Reference System,
// i.e., the intermediate equator.
// The x axis is the Celestial Intermediate Origin.
// The GCRS is related to the Celestial Intermediate Reference System by
// precession-nutation and frame biases, see sections 5.4.4 and 5.5.4 of the
// IERS conventions (2010).
// TODO(egg): identifying this with the GCRS leads to errors on the order of 10
// arcminutes at the time of this writing, and on the order of a degree over a
// century.
using CelestialIntermediateReferenceSystem = GCRS;

// A reference frame for transit exoplanetology.
// The xy plane is the plane of the sky.  The origin is at the barycentre of the
// extrasolar system.  The z axis goes from the extrasolar system to the Earth.
// The xz plane is (approximately) the plane of the extrasolar system.
using Sky =
    Frame<serialization::Frame::SolarSystemTag,
          serialization::Frame::SKY, true>;

}  // namespace internal_frames

using internal_frames::ICRS;
using internal_frames::GCRS;
using internal_frames::ITRS;
using internal_frames::Sky;

}  // namespace astronomy
}  // namespace principia
<commit_msg>bcrs?<commit_after>
#pragma once

#include <functional>

#include "geometry/frame.hpp"
#include "geometry/named_quantities.hpp"
#include "quantities/si.hpp"
#include "serialization/geometry.pb.h"

namespace principia {
namespace astronomy {
namespace internal_frames {

using geometry::Frame;
using geometry::Instant;
using geometry::Position;
using quantities::si::ArcMinute;
using quantities::si::ArcSecond;
using quantities::si::Degree;

// The International Celestial Reference System.
// The origin is the barycentre of the solar system.  The axes are fixed with
// respect to the quasars.
// The xy plane is close to the mean equator at J2000.0.
// The x axis is close to the dynamical equinox at J2000.
// The z axis is perpendicular to the xy plane and points to the northern side
// of the xy plane.
// To be honest:
// - There are several realizations of the ICRS, namely ICRF (ICRF1) and its
//   extensions, ICRF2, and the optical Hipparcos Celestial Reference Frame
//   (HCRF); these realizations have different errors, but are consistent. ICRF3
//   is in preparation, as well as an optical realization based on Gaia data.
// - The terms Barycentric Celestial Reference System (BCRS) and ICRS are often
//   used interchangeably; the relativistic framework, including the metric
//   tensor, is defined for the BCRS (IAU 2000 resolution B1.3); the orientation
//   of the BCRS is given by the ICRS axes unless otherwise stated (IAU 2006
//   resolution B2 recommendation 2).
using ICRS = Frame<serialization::Frame::SolarSystemTag,
                   serialization::Frame::ICRS,
                   /*frame_is_inertial=*/true>;

// The Geocentric Celestial Reference System.
// The origin is the centre of mass of the whole Earth system, including oceans
// and atmosphere; the axes are those of the ICRS.
// To be honest:
// - The BCRS and GCRS are relativistic reference systems.
// - The transformation between BCRS and GCRS spatial coordinates has no
//   rotational component, i.e., the GCRS is kinematically non-rotating with
//   respect to the BCRS; as a result, it rotates dynamically with respect to
//   the BCRS; in particular, the equations of motion in the GCRS include de
//   Sitter and Lense–Thirring precession.
// - The time coordinate of the BCRS is TCB, and the time coordinate of the GCRS
//   is TCG; TT is a linear scaling of TCG, and TDB is a linear scaling of TDB;
//   for practical purposes TT and TDB are within 2 ms of each other;
//   Principia's |Instant| is TT.
using GCRS = Frame<serialization::Frame::SolarSystemTag,
                   serialization::Frame::GCRS,
                   /*frame_is_inertial=*/false>;

// The International Terrestrial Reference System.
// The origin is the centre of mass of the whole Earth system, including oceans
// and atmosphere; there is no global residual rotation with respect to
// horizontal motions at the earth's surface.
// Practical notes:
// - This is identical to WGS84 at 1 m level, and to recent realizations of WGS
//   84 at 10 cm level; the xz plane is a bit over a hundred metres from the
//   Royal Observatory in Greenwich.
//   Caveat: using |SphericalCoordinates<Length>| on ITRS coordinates is
//   inconsistent with WGS 84 latitudes; the WGS 84 geoid should be used.
// - The ITRS is related to the European Terrestrial Reference System (ETRS89)
//   by a time-dependent rigid transformation.
// To be honest:
// - There are many realizations of the ITRS; as of this writing, ICRFs 89, 90,
//   91, 92, 93, 94, 96, 97, 2000, 2005, 2008, and 2014.  They are related by
//   linearly time-dependent linearized similarity transformations with nonzero
//   scaling, which the current abstractions of Principia cannot support; see
//   Transformation parameters from ITRF2014 to past ITRFs,
//   http://itrf.ensg.ign.fr/doc_ITRF/Transfo-ITRF2014_ITRFs.txt.  Identifying
//   recent ITRFs (2005 and later) results in errors of a few millimetres at the
//   geocentre, scale errors on the order of 1 part-per-billion, and angular
//   errors below 1 μas.  Identifying earlier ITRFs results in errors may result
//   in errors of tens of centimetres at the geocentre, scale errors on the
//   order of ten parts per billion, and arcsecond-level angular errors.
// - ETRFyy is always related to the corresponding ITRFyy by a linearized rigid
//   transformation depending linearly on time, however it is related to other
//   ITRFs by time-dependent similarity with time-dependent nonzero scaling; see
//   the tables in EUREF Technical Note 1,
//   http://etrs89.ensg.ign.fr/pub/EUREF-TN-1.pdf
using ITRS = Frame<serialization::Frame::SolarSystemTag,
                   serialization::Frame::ITRS,
                   /*frame_is_inertial=*/false>;

// The following two reference systems are both geocentric, and they share the
// same z axis, the Celestial Intermediate Pole.  Their common xy plane is the
// intermediate equator.
// The rotation around the z axis relating the Terrestrial and Celestial
// Intermediate Reference Systems, i.e., the angle between the Terrestrial and
// Celestial Intermediate Origins, is the Earth Rotation Angle (ERA); the Earth
// Rotation Angle is an affine function of UT1 defined by equation 5.14 of the
// IERS conventions (2010).  Note that the rate is faster than 2π radians per
// UT1 day, as UT1 is notionally mean solar days, whereas revolutions of the ERA
// are stellar days.

// The glossary of the Nomenclature for Fundamental Astronomy notes for both
// that "since the acronym for this system is close to another acronym (namely
// [ITRS, respectively ICRS]), it is suggested that wherever possible the
// complete name be used".

// The Terrestrial Intermediate Reference System.
// The x axis is the Terrestrial Intermediate Origin.
// The ITRS is related to the Terrestrial Intermediate Reference System by polar
// motion, as described in sections 5.4.1 and 5.5.1 of the IERS conventions
// (2010).
// TODO(egg): identifying this with the ITRS, besides leading to acronym
// confusion, results in arcsecond-level errors.
using TerrestrialIntermediateReferenceSystem = ITRS;

// The origin is geocentric; the basis is right-handed and orthonormal, the xy
// plane is the same as that of the Terrestrial Intermediate Reference System,
// i.e., the intermediate equator.
// The x axis is the Celestial Intermediate Origin.
// The GCRS is related to the Celestial Intermediate Reference System by
// precession-nutation and frame biases, see sections 5.4.4 and 5.5.4 of the
// IERS conventions (2010).
// TODO(egg): identifying this with the GCRS leads to errors on the order of 10
// arcminutes at the time of this writing, and on the order of a degree over a
// century.
using CelestialIntermediateReferenceSystem = GCRS;

// A reference frame for transit exoplanetology.
// The xy plane is the plane of the sky.  The origin is at the barycentre of the
// extrasolar system.  The z axis goes from the extrasolar system to the Earth.
// The xz plane is (approximately) the plane of the extrasolar system.
using Sky =
    Frame<serialization::Frame::SolarSystemTag,
          serialization::Frame::SKY, true>;

}  // namespace internal_frames

using internal_frames::ICRS;
using internal_frames::GCRS;
using internal_frames::ITRS;
using internal_frames::Sky;

}  // namespace astronomy
}  // namespace principia
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "leveldb.h"
#include "util.h"

#include <leveldb/env.h>
#include <leveldb/cache.h>
#include <leveldb/filter_policy.h>
#include <memenv/memenv.h>

#include <boost/filesystem.hpp>

void HandleError(const leveldb::Status &status) throw(leveldb_error) {
    if (status.ok())
        return;
    if (status.IsCorruption())
        throw leveldb_error("Database corrupted");
    if (status.IsIOError())
        throw leveldb_error("Database I/O error");
    if (status.IsNotFound())
        throw leveldb_error("Database entry missing");
    throw leveldb_error("Unknown database error");
}

static leveldb::Options GetOptions(size_t nCacheSize) {
    leveldb::Options options;
    options.block_cache = leveldb::NewLRUCache(nCacheSize / 2);
    options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously
    options.filter_policy = leveldb::NewBloomFilterPolicy(10);
    options.compression = leveldb::kNoCompression;
    return options;
}

CLevelDB::CLevelDB(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory, bool fWipe) {
    penv = NULL;
    readoptions.verify_checksums = true;
    iteroptions.verify_checksums = true;
    iteroptions.fill_cache = false;
    syncoptions.sync = true;
    options = GetOptions(nCacheSize);
    options.create_if_missing = true;
    if (fMemory) {
        penv = leveldb::NewMemEnv(leveldb::Env::Default());
        options.env = penv;
    } else {
        if (fWipe) {
            printf("Wiping LevelDB in %s\n", path.string().c_str());
            leveldb::DestroyDB(path.string(), options);
        }
        boost::filesystem::create_directory(path);
        printf("Opening LevelDB in %s\n", path.string().c_str());
    }
    leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb);
    if (!status.ok())
        throw std::runtime_error(strprintf("CLevelDB(): error opening database environment %s", status.ToString().c_str()));
    printf("Opened LevelDB successfully\n");
}

CLevelDB::~CLevelDB() {
    delete pdb;
    pdb = NULL;
    delete options.filter_policy;
    options.filter_policy = NULL;
    delete options.block_cache;
    options.block_cache = NULL;
    delete penv;
    options.env = NULL;
}

bool CLevelDB::WriteBatch(CLevelDBBatch &batch, bool fSync) throw(leveldb_error) {
    leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
    if (!status.ok()) {
        printf("LevelDB write failure: %s\n", status.ToString().c_str());
        HandleError(status);
        return false;
    }
    return true;
}
<commit_msg>Reduce number of open LevelDB files to 64<commit_after>// Copyright (c) 2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "leveldb.h"
#include "util.h"

#include <leveldb/env.h>
#include <leveldb/cache.h>
#include <leveldb/filter_policy.h>
#include <memenv/memenv.h>

#include <boost/filesystem.hpp>

void HandleError(const leveldb::Status &status) throw(leveldb_error) {
    if (status.ok())
        return;
    if (status.IsCorruption())
        throw leveldb_error("Database corrupted");
    if (status.IsIOError())
        throw leveldb_error("Database I/O error");
    if (status.IsNotFound())
        throw leveldb_error("Database entry missing");
    throw leveldb_error("Unknown database error");
}

static leveldb::Options GetOptions(size_t nCacheSize) {
    leveldb::Options options;
    options.block_cache = leveldb::NewLRUCache(nCacheSize / 2);
    options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously
    options.filter_policy = leveldb::NewBloomFilterPolicy(10);
    options.compression = leveldb::kNoCompression;
    options.max_open_files = 64;
    return options;
}

CLevelDB::CLevelDB(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory, bool fWipe) {
    penv = NULL;
    readoptions.verify_checksums = true;
    iteroptions.verify_checksums = true;
    iteroptions.fill_cache = false;
    syncoptions.sync = true;
    options = GetOptions(nCacheSize);
    options.create_if_missing = true;
    if (fMemory) {
        penv = leveldb::NewMemEnv(leveldb::Env::Default());
        options.env = penv;
    } else {
        if (fWipe) {
            printf("Wiping LevelDB in %s\n", path.string().c_str());
            leveldb::DestroyDB(path.string(), options);
        }
        boost::filesystem::create_directory(path);
        printf("Opening LevelDB in %s\n", path.string().c_str());
    }
    leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb);
    if (!status.ok())
        throw std::runtime_error(strprintf("CLevelDB(): error opening database environment %s", status.ToString().c_str()));
    printf("Opened LevelDB successfully\n");
}

CLevelDB::~CLevelDB() {
    delete pdb;
    pdb = NULL;
    delete options.filter_policy;
    options.filter_policy = NULL;
    delete options.block_cache;
    options.block_cache = NULL;
    delete penv;
    options.env = NULL;
}

bool CLevelDB::WriteBatch(CLevelDBBatch &batch, bool fSync) throw(leveldb_error) {
    leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
    if (!status.ok()) {
        printf("LevelDB write failure: %s\n", status.ToString().c_str());
        HandleError(status);
        return false;
    }
    return true;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <pqxx/pqxx>

using namespace std;
using namespace pqxx;

// clang++ update.cpp -o update -lpqxx -lpq

int main() {
   const char * sql;

   try {
      connection C("dbname=benchcare user=synod password= \
      hostaddr=127.0.0.1 port=5432");
      if (C.is_open()) {
         cout << "Opened database successfully: " << C.dbname() << endl;
      } else {
         cout << "Can't open database" << endl;
         return 1;
      }

      /* Create a transactional object. */
      work W(C);
      /* Create  SQL UPDATE statement */
      sql = "UPDATE COMPANY set SALARY = 25000.00 where ID=1";
      /* Execute SQL query */
      W.exec( sql );
      W.commit();
      cout << "Records updated successfully" << endl;

      /* Create SQL SELECT statement */
      sql = "SELECT * from COMPANY";

      /* Create a non-transactional object. */
      nontransaction N(C);

      /* Execute SQL query */
      result R( N.exec( sql ));

      /* List down all the records */
      for (result::const_iterator c = R.begin(); c != R.end(); ++c) {
         cout << "ID = " << c[0].as<int>() << endl;
         cout << "Name = " << c[1].as<string>() << endl;
         cout << "Age = " << c[2].as<int>() << endl;
         cout << "Address = " << c[3].as<string>() << endl;
         cout << "Salary = " << c[4].as<float>() << endl;
      }
      cout << "Operation done successfully" << endl;
      C.disconnect ();
   } catch (const std::exception &e) {
      cerr << e.what() << std::endl;
      return 1;
   }

   return 0;
}
<commit_msg>update ops<commit_after>#include <iostream>
#include <pqxx/pqxx>

using namespace std;
using namespace pqxx;

// clang++ update.cpp -o update -lpqxx -lpq

int main() {
   const char * sql;

   try {
      connection C("dbname=benchcare user=synod password= \
      hostaddr=127.0.0.1 port=5432");
      if (C.is_open()) {
         cout << "Opened database successfully: " << C.dbname() << endl;
      } else {
         cout << "Can't open database" << endl;
         return 1;
      }

      /* Create a transactional object. */
      work W(C);
      /* Create  SQL UPDATE statement */
      sql = "UPDATE COMPANY set SALARY = 25000.00 where ID=1";
      /* Execute SQL query */
      W.exec( sql );
      W.commit();
      cout << "Records updated successfully" << endl;

      /* Create SQL SELECT statement */
      sql = "SELECT * from COMPANY";

      /* Create a non-transactional object. */
      nontransaction N(C);

      /* Execute SQL query */
      result R( N.exec( sql ));

      /* List down all the records */
      for (result::const_iterator c = R.begin(); c != R.end(); ++c) {
         cout << "ID = " << c[0].as<int>() << endl;
         cout << "Name = " << c[1].as<string>() << endl;
         cout << "Age = " << c[2].as<int>() << endl;
         cout << "Address = " << c[3].as<string>() << endl;
         cout << "Salary = " << c[4].as<float>() << endl;
      }
      cout << "Operation done successfully" << endl;
      C.disconnect ();
   } catch (const std::exception &e) {
      cerr << e.what() << std::endl;
      return 1;
   }

   return 0;
}
<|endoftext|>


<commit_before>/* RedLock implement DLM(Distributed Lock Manager) with cpp.
 *
 * Copyright (c) 2014, jacketzhong <jacketzhong at gmail dot com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of Redis nor the names of its contributors may be used
 *     to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <math.h>
#include "redlock.h"

/* Turn the plain C strings into Sds strings */
static char **convertToSds(int count, char** args) {
    int j;
    char **sds = (char**)malloc(sizeof(char*)*count);
    for(j = 0; j < count; j++)
        sds[j] = sdsnew(args[j]);
    return sds;
}

CLock::CLock() : m_validityTime(0), m_resource(NULL), m_val(NULL) {
}

CLock::~CLock() {
    sdsfree(m_resource);
    sdsfree(m_val);
}

int CRedLock::m_defaultRetryCount = 3;
int CRedLock::m_defaultRetryDelay = 200;
float CRedLock::m_clockDriftFactor = 0.01;

// ----------------
// init redlock
// ----------------
CRedLock::CRedLock() {
    Initialize();
}

// ----------------
// release redlock
// ----------------
CRedLock::~CRedLock() {
    sdsfree(m_continueLockScript);
    sdsfree(m_unlockScript);
    close(m_fd);
    /* Disconnects and frees the context */
    for (int i = 0; i < (int)m_redisServer.size(); i++) {
        redisFree(m_redisServer[i]);
    }
}

// ----------------
// Initialize the server: scripts...
// ----------------
bool CRedLock::Initialize() {
    m_continueLockScript = sdsnew("if redis.call('get', KEYS[1]) == ARGV[1] then redis.call('del', KEYS[1]) end return redis.call('set', KEYS[1], ARGV[2], 'px', ARGV[3], 'nx')");
    m_unlockScript       = sdsnew("if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end");
    m_retryCount = m_defaultRetryCount;
    m_retryDelay = m_defaultRetryDelay;
    m_quoRum     = 0;
    // open rand file
    m_fd = open("/dev/urandom", O_RDONLY);
    if (m_fd == -1) {
        //Open error handling
        printf("Can't open file /dev/urandom\n");
        exit(-1);
        return false;
    }
    return true;
}

// ----------------
// add redis server
// ----------------
bool CRedLock::AddServerUrl(const char *ip, const int port) {
    redisContext *c;
    struct timeval timeout = { 1, 500000 }; // 1.5 seconds
    c = redisConnectWithTimeout(ip, port, timeout);
    if (c) {
        m_redisServer.push_back(c);
    }
    m_quoRum = (int)m_redisServer.size() / 2 + 1;
    return true;
}

// ----------------
// set retry
// ----------------
void CRedLock::SetRetry(const int count, const int delay) {
    m_retryCount = count;
    m_retryDelay = delay;
}

// ----------------
// lock the resource
// ----------------
bool CRedLock::Lock(const char *resource, const int ttl, CLock &lock) {
    sds val = GetUniqueLockId();
    if (!val) {
        return false;
    }
    lock.m_resource = sdsnew(resource);
    lock.m_val = val;
    printf("Get the unique id is %s\n", val);
    int retryCount = m_retryCount;
    do {
        int n = 0;
        int startTime = (int)time(NULL) * 1000;
        int slen = (int)m_redisServer.size();
        for (int i = 0; i < slen; i++) {
            if (LockInstance(m_redisServer[i], resource, val, ttl)) {
                n++;
            }
        }
        //Add 2 milliseconds to the drift to account for Redis expires
        //precision, which is 1 millisecond, plus 1 millisecond min drift
        //for small TTLs.
        int drift = (ttl * m_clockDriftFactor) + 2;
        int validityTime = ttl - ((int)time(NULL) * 1000 - startTime) - drift;
        printf("The resource validty time is %d, n is %d, quo is %d\n",
               validityTime, n, m_quoRum);
        if (n >= m_quoRum && validityTime > 0) {
            lock.m_validityTime = validityTime;
            return true;
        } else {
            Unlock(lock);
        }
        // Wait a random delay before to retry
        int delay = rand() % m_retryDelay + floor(m_retryDelay / 2);
        usleep(delay * 1000);
        retryCount--;
    } while (retryCount > 0);
    return false;
}

// ----------------
// release resource
// ----------------
bool CRedLock::ContinueLock(const char *resource, const int ttl, CLock &lock) {
    sds val = GetUniqueLockId();
    if (!val) {
        return false;
    }
    lock.m_resource = sdsnew(resource);
    lock.m_val = val;
    if (m_continueLock.m_resource == NULL) {
        m_continueLock.m_resource = sdsnew(resource);
        m_continueLock.m_val = sdsnew(val);
    }
    printf("Get the unique id is %s\n", val);
    int retryCount = m_retryCount;
    do {
        int n = 0;
        int startTime = (int)time(NULL) * 1000;
        int slen = (int)m_redisServer.size();
        for (int i = 0; i < slen; i++) {
            if (ContinueLockInstance(m_redisServer[i], resource, val, ttl)) {
                n++;
            }
        }
        // update old val
        sdsfree(m_continueLock.m_val);
        m_continueLock.m_val = sdsnew(val);
        //Add 2 milliseconds to the drift to account for Redis expires
        //precision, which is 1 millisecond, plus 1 millisecond min drift
        //for small TTLs.
        int drift = (ttl * m_clockDriftFactor) + 2;
        int validityTime = ttl - ((int)time(NULL) * 1000 - startTime) - drift;
        printf("The resource validty time is %d, n is %d, quo is %d\n",
               validityTime, n, m_quoRum);
        if (n >= m_quoRum && validityTime > 0) {
            lock.m_validityTime = validityTime;
            return true;
        } else {
            Unlock(lock);
        }
        // Wait a random delay before to retry
        int delay = rand() % m_retryDelay + floor(m_retryDelay / 2);
        usleep(delay * 1000);
        retryCount--;
    } while (retryCount > 0);
    return false;
}

// ----------------
// lock the resource
// ----------------
bool CRedLock::Unlock(const CLock &lock) {
    int slen = (int)m_redisServer.size();
    for (int i = 0; i < slen; i++) {
        UnlockInstance(m_redisServer[i], lock.m_resource, lock.m_val);
    }
    return true;
}

// ----------------
// lock the resource milliseconds
// ----------------
bool CRedLock::LockInstance(redisContext *c, const char *resource,
                            const char *val, const int ttl) {
    redisReply *reply;
    reply = (redisReply *)redisCommand(c, "set %s %s px %d nx",
                                       resource, val, ttl);
    printf("Set return: %s [null == fail, OK == success]\n", reply->str);
    if (reply->str && strcmp(reply->str, "OK") == 0) {
        freeReplyObject(reply);
        return true;
    }
    freeReplyObject(reply);
    return false;
}

// ----------------
// 对redismaster续锁, 私有函数
// ----------------
bool CRedLock::ContinueLockInstance(redisContext *c, const char *resource,
                                    const char *val, const int ttl) {
    int argc = 7;
    sds sdsTTL = sdsempty();
    sdsTTL = sdscatprintf(sdsTTL, "%d", ttl);
    char *continueLockScriptArgv[] = {(char*)"EVAL",
                                      m_continueLockScript,
                                      (char*)"1",
                                      (char*)resource,
                                      m_continueLock.m_val,
                                      (char*)val,
                                      sdsTTL};
    redisReply *reply = RedisCommandArgv(c, argc, continueLockScriptArgv);
    sdsfree(sdsTTL);
    printf("Set return: %s [null == fail, OK == success]\n", reply->str);
    if (reply->str && strcmp(reply->str, "OK") == 0) {
        freeReplyObject(reply);
        return true;
    }
    freeReplyObject(reply);
    return false;
}

// ----------------
// 对redismaster解锁
// ----------------
void CRedLock::UnlockInstance(redisContext *c, const char *resource,
                              const char *val) {
    int argc = 5;
    char *unlockScriptArgv[] = {(char*)"EVAL",
                                m_unlockScript,
                                (char*)"1",
                                (char*)resource,
                                (char*)val};
    redisReply *reply = RedisCommandArgv(c, argc, unlockScriptArgv);
    freeReplyObject(reply);
}

// ----------------
// 对redismaster执行脚本命令
// ----------------
redisReply * CRedLock::RedisCommandArgv(redisContext *c, int argc, char **inargv) {
    char **argv;
    argv = convertToSds(argc, inargv);
    /* Setup argument length */
    size_t *argvlen;
    argvlen = (size_t *)malloc(argc * sizeof(size_t));
    for (int j = 0; j < argc; j++)
        argvlen[j] = sdslen(argv[j]);
    redisReply *reply = NULL;
    reply = (redisReply *)redisCommandArgv(c, argc, (const char **)argv, argvlen);
    printf("RedisCommandArgv return: %lld\n", reply->integer);
    free(argvlen);
    sdsfreesplitres(argv, argc);
    return reply;
}

// ----------------
// 获取唯一id
// ----------------
sds CRedLock::GetUniqueLockId() {
    unsigned char buffer[20];
    if (read(m_fd, buffer, sizeof(buffer)) == sizeof(buffer)) {
        //获取20byte的随机数据
        sds s;
        s = sdsempty();
        for (int i = 0; i < 20; i++) {
            s = sdscatprintf(s, "%02X", buffer[i]);
        }
        return s;
    } else {
        //读取失败
        printf("Error: GetUniqueLockId %d\n", __LINE__);
    }
    return NULL;
}
<commit_msg>fix the crash problem because of redis master crash<commit_after>/* RedLock implement DLM(Distributed Lock Manager) with cpp.
 *
 * Copyright (c) 2014, jacketzhong <jacketzhong at gmail dot com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of Redis nor the names of its contributors may be used
 *     to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <math.h>
#include "redlock.h"

/* Turn the plain C strings into Sds strings */
static char **convertToSds(int count, char** args) {
    int j;
    char **sds = (char**)malloc(sizeof(char*)*count);
    for(j = 0; j < count; j++)
        sds[j] = sdsnew(args[j]);
    return sds;
}

CLock::CLock() : m_validityTime(0), m_resource(NULL), m_val(NULL) {
}

CLock::~CLock() {
    sdsfree(m_resource);
    sdsfree(m_val);
}

int CRedLock::m_defaultRetryCount = 3;
int CRedLock::m_defaultRetryDelay = 200;
float CRedLock::m_clockDriftFactor = 0.01;

// ----------------
// init redlock
// ----------------
CRedLock::CRedLock() {
    Initialize();
}

// ----------------
// release redlock
// ----------------
CRedLock::~CRedLock() {
    sdsfree(m_continueLockScript);
    sdsfree(m_unlockScript);
    close(m_fd);
    /* Disconnects and frees the context */
    for (int i = 0; i < (int)m_redisServer.size(); i++) {
        redisFree(m_redisServer[i]);
    }
}

// ----------------
// Initialize the server: scripts...
// ----------------
bool CRedLock::Initialize() {
    m_continueLockScript = sdsnew("if redis.call('get', KEYS[1]) == ARGV[1] then redis.call('del', KEYS[1]) end return redis.call('set', KEYS[1], ARGV[2], 'px', ARGV[3], 'nx')");
    m_unlockScript       = sdsnew("if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end");
    m_retryCount = m_defaultRetryCount;
    m_retryDelay = m_defaultRetryDelay;
    m_quoRum     = 0;
    // open rand file
    m_fd = open("/dev/urandom", O_RDONLY);
    if (m_fd == -1) {
        //Open error handling
        printf("Can't open file /dev/urandom\n");
        exit(-1);
        return false;
    }
    return true;
}

// ----------------
// add redis server
// ----------------
bool CRedLock::AddServerUrl(const char *ip, const int port) {
    redisContext *c;
    struct timeval timeout = { 1, 500000 }; // 1.5 seconds
    c = redisConnectWithTimeout(ip, port, timeout);
    if (c) {
        m_redisServer.push_back(c);
    }
    m_quoRum = (int)m_redisServer.size() / 2 + 1;
    return true;
}

// ----------------
// set retry
// ----------------
void CRedLock::SetRetry(const int count, const int delay) {
    m_retryCount = count;
    m_retryDelay = delay;
}

// ----------------
// lock the resource
// ----------------
bool CRedLock::Lock(const char *resource, const int ttl, CLock &lock) {
    sds val = GetUniqueLockId();
    if (!val) {
        return false;
    }
    lock.m_resource = sdsnew(resource);
    lock.m_val = val;
    printf("Get the unique id is %s\n", val);
    int retryCount = m_retryCount;
    do {
        int n = 0;
        int startTime = (int)time(NULL) * 1000;
        int slen = (int)m_redisServer.size();
        for (int i = 0; i < slen; i++) {
            if (LockInstance(m_redisServer[i], resource, val, ttl)) {
                n++;
            }
        }
        //Add 2 milliseconds to the drift to account for Redis expires
        //precision, which is 1 millisecond, plus 1 millisecond min drift
        //for small TTLs.
        int drift = (ttl * m_clockDriftFactor) + 2;
        int validityTime = ttl - ((int)time(NULL) * 1000 - startTime) - drift;
        printf("The resource validty time is %d, n is %d, quo is %d\n",
               validityTime, n, m_quoRum);
        if (n >= m_quoRum && validityTime > 0) {
            lock.m_validityTime = validityTime;
            return true;
        } else {
            Unlock(lock);
        }
        // Wait a random delay before to retry
        int delay = rand() % m_retryDelay + floor(m_retryDelay / 2);
        usleep(delay * 1000);
        retryCount--;
    } while (retryCount > 0);
    return false;
}

// ----------------
// release resource
// ----------------
bool CRedLock::ContinueLock(const char *resource, const int ttl, CLock &lock) {
    sds val = GetUniqueLockId();
    if (!val) {
        return false;
    }
    lock.m_resource = sdsnew(resource);
    lock.m_val = val;
    if (m_continueLock.m_resource == NULL) {
        m_continueLock.m_resource = sdsnew(resource);
        m_continueLock.m_val = sdsnew(val);
    }
    printf("Get the unique id is %s\n", val);
    int retryCount = m_retryCount;
    do {
        int n = 0;
        int startTime = (int)time(NULL) * 1000;
        int slen = (int)m_redisServer.size();
        for (int i = 0; i < slen; i++) {
            if (ContinueLockInstance(m_redisServer[i], resource, val, ttl)) {
                n++;
            }
        }
        // update old val
        sdsfree(m_continueLock.m_val);
        m_continueLock.m_val = sdsnew(val);
        //Add 2 milliseconds to the drift to account for Redis expires
        //precision, which is 1 millisecond, plus 1 millisecond min drift
        //for small TTLs.
        int drift = (ttl * m_clockDriftFactor) + 2;
        int validityTime = ttl - ((int)time(NULL) * 1000 - startTime) - drift;
        printf("The resource validty time is %d, n is %d, quo is %d\n",
               validityTime, n, m_quoRum);
        if (n >= m_quoRum && validityTime > 0) {
            lock.m_validityTime = validityTime;
            return true;
        } else {
            Unlock(lock);
        }
        // Wait a random delay before to retry
        int delay = rand() % m_retryDelay + floor(m_retryDelay / 2);
        usleep(delay * 1000);
        retryCount--;
    } while (retryCount > 0);
    return false;
}

// ----------------
// lock the resource
// ----------------
bool CRedLock::Unlock(const CLock &lock) {
    int slen = (int)m_redisServer.size();
    for (int i = 0; i < slen; i++) {
        UnlockInstance(m_redisServer[i], lock.m_resource, lock.m_val);
    }
    return true;
}

// ----------------
// lock the resource milliseconds
// ----------------
bool CRedLock::LockInstance(redisContext *c, const char *resource,
                            const char *val, const int ttl) {
    redisReply *reply;
    reply = (redisReply *)redisCommand(c, "set %s %s px %d nx",
                                       resource, val, ttl);
    if (reply) {
        printf("Set return: %s [null == fail, OK == success]\n", reply->str);
    }
    if (reply && reply->str && strcmp(reply->str, "OK") == 0) {
        freeReplyObject(reply);
        return true;
    }
    if (reply) {
        freeReplyObject(reply);
    }
    return false;
}

// ----------------
// 对redismaster续锁, 私有函数
// ----------------
bool CRedLock::ContinueLockInstance(redisContext *c, const char *resource,
                                    const char *val, const int ttl) {
    int argc = 7;
    sds sdsTTL = sdsempty();
    sdsTTL = sdscatprintf(sdsTTL, "%d", ttl);
    char *continueLockScriptArgv[] = {(char*)"EVAL",
                                      m_continueLockScript,
                                      (char*)"1",
                                      (char*)resource,
                                      m_continueLock.m_val,
                                      (char*)val,
                                      sdsTTL};
    redisReply *reply = RedisCommandArgv(c, argc, continueLockScriptArgv);
    sdsfree(sdsTTL);
    if (reply) {
        printf("Set return: %s [null == fail, OK == success]\n", reply->str);
    }
    if (reply && reply->str && strcmp(reply->str, "OK") == 0) {
        freeReplyObject(reply);
        return true;
    }
    if (reply) {
        freeReplyObject(reply);
    }
    return false;
}

// ----------------
// 对redismaster解锁
// ----------------
void CRedLock::UnlockInstance(redisContext *c, const char *resource,
                              const char *val) {
    int argc = 5;
    char *unlockScriptArgv[] = {(char*)"EVAL",
                                m_unlockScript,
                                (char*)"1",
                                (char*)resource,
                                (char*)val};
    redisReply *reply = RedisCommandArgv(c, argc, unlockScriptArgv);
    if (reply) {
        freeReplyObject(reply);
    }
}

// ----------------
// 对redismaster执行脚本命令
// ----------------
redisReply * CRedLock::RedisCommandArgv(redisContext *c, int argc, char **inargv) {
    char **argv;
    argv = convertToSds(argc, inargv);
    /* Setup argument length */
    size_t *argvlen;
    argvlen = (size_t *)malloc(argc * sizeof(size_t));
    for (int j = 0; j < argc; j++)
        argvlen[j] = sdslen(argv[j]);
    redisReply *reply = NULL;
    reply = (redisReply *)redisCommandArgv(c, argc, (const char **)argv, argvlen);
    if (reply) {
        printf("RedisCommandArgv return: %lld\n", reply->integer);
    }
    free(argvlen);
    sdsfreesplitres(argv, argc);
    return reply;
}

// ----------------
// 获取唯一id
// ----------------
sds CRedLock::GetUniqueLockId() {
    unsigned char buffer[20];
    if (read(m_fd, buffer, sizeof(buffer)) == sizeof(buffer)) {
        //获取20byte的随机数据
        sds s;
        s = sdsempty();
        for (int i = 0; i < 20; i++) {
            s = sdscatprintf(s, "%02X", buffer[i]);
        }
        return s;
    } else {
        //读取失败
        printf("Error: GetUniqueLockId %d\n", __LINE__);
    }
    return NULL;
}
<|endoftext|>


<commit_before>#include "tangram.h"

#include "platform.h"
#include "scene/scene.h"
#include "scene/sceneLoader.h"
#include "style/style.h"
#include "text/fontContext.h"
#include "labels/labels.h"
#include "tile/tileManager.h"
#include "tile/tile.h"
#include "gl/error.h"
#include "gl/shaderProgram.h"
#include "scene/skybox.h"
#include "view/view.h"
#include "gl/renderState.h"
#include "gl/primitives.h"
#include "util/inputHandler.h"
#include <memory>
#include <cmath>
#include <bitset>

namespace Tangram {

std::unique_ptr<TileManager> m_tileManager;
std::shared_ptr<Scene> m_scene;
std::shared_ptr<View> m_view;
std::unique_ptr<Labels> m_labels;
std::shared_ptr<FontContext> m_ftContext;
std::unique_ptr<Skybox> m_skybox;
std::unique_ptr<InputHandler> m_inputHandler;

static float g_time = 0.0;
static std::bitset<8> g_flags = 0;

void initialize(const char* _scenePath) {

    logMsg("initialize\n");

    if (!m_tileManager) {

        // Create view
        m_view = std::make_shared<View>();

        // Create a scene object
        m_scene = std::make_shared<Scene>();

        // Input handler
        m_inputHandler = std::unique_ptr<InputHandler>(new InputHandler(m_view));

        m_skybox = std::unique_ptr<Skybox>(new Skybox("cubemap.png"));
        m_skybox->init();

        // Create a tileManager
        m_tileManager = TileManager::GetInstance();

        // Pass references to the view and scene into the tile manager
        m_tileManager->setView(m_view);
        m_tileManager->setScene(m_scene);

        // Font and label setup
        m_ftContext = FontContext::GetInstance();
        m_ftContext->addFont("FiraSans-Medium.ttf", "FiraSans");
        m_labels = std::unique_ptr<Labels>(new Labels());

        logMsg("Loading Tangram scene file: %s\n", _scenePath);
        auto sceneString = stringFromResource(_scenePath);

        SceneLoader loader;

        loader.loadScene(sceneString, *m_scene, *m_tileManager, *m_view);

    }

    logMsg("finish initialize\n");

}

void resize(int _newWidth, int _newHeight) {

    logMsg("resize: %d x %d\n", _newWidth, _newHeight);

    glViewport(0, 0, _newWidth, _newHeight);

    if (m_view) {
        m_view->setSize(_newWidth, _newHeight);
    }

    for (auto& style : m_scene->styles()) {
        style->viewportHasChanged();
    }

    Primitives::setResolution(_newWidth, _newHeight);

    while (Error::hadGlError("Tangram::resize()")) {}

}

void update(float _dt) {

    g_time += _dt;

    m_inputHandler->update(_dt);

    m_view->update();

    m_tileManager->updateTileSets();

    if (m_view->changedOnLastUpdate() || m_tileManager->hasTileSetChanged() || m_labels->needUpdate()) {

        auto& tiles = m_tileManager->getVisibleTiles();

        for (const auto& tile : tiles) {
            tile->update(_dt, *m_view);
        }

        m_labels->update(*m_view, _dt, m_scene->styles(), tiles);
    }

    if (m_scene) {
        // Update lights and styles
    }
}

void render() {

    // Set up openGL for new frame
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Loop over all styles
    for (const auto& style : m_scene->styles()) {
        style->onBeginDrawFrame(*m_view, *m_scene);

        // Loop over all tiles in m_tileSet
        for (const auto& tile : m_tileManager->getVisibleTiles()) {
            tile->draw(*style, *m_view);
        }

        style->onEndDrawFrame();
    }

    m_skybox->draw(*m_view);

    m_labels->drawDebug(*m_view);

    while (Error::hadGlError("Tangram::render()")) {}
}

void setPosition(double _lon, double _lat) {

    glm::dvec2 meters = m_view->getMapProjection().LonLatToMeters({ _lon, _lat});
    m_view->setPosition(meters.x, meters.y);
    requestRender();

}

void getPosition(double& _lon, double& _lat) {

    glm::dvec2 meters(m_view->getPosition().x, m_view->getPosition().y);
    glm::dvec2 degrees = m_view->getMapProjection().MetersToLonLat(meters);
    _lon = degrees.x;
    _lat = degrees.y;

}

void setZoom(float _z) {

    m_view->setZoom(_z);
    requestRender();

}

float getZoom() {

    return m_view->getZoom();

}

void setRotation(float _radians) {

    m_view->setRoll(_radians);
    requestRender();

}

float getRotation() {

    return m_view->getRoll();

}

void setTilt(float _radians) {

    m_view->setPitch(_radians);
    requestRender();

}

float getTilt() {

    return m_view->getPitch();

}

void screenToWorldCoordinates(double& _x, double& _y) {

    float screenX = _x, screenY = _y;
    m_view->screenToGroundPlane(screenX, screenY);
    glm::dvec2 meters(screenX + m_view->getPosition().x, screenY + m_view->getPosition().y);
    glm::dvec2 lonLat = m_view->getMapProjection().MetersToLonLat(meters);
    _x = lonLat.x;
    _y = lonLat.y;

}

void setPixelScale(float _pixelsPerPoint) {

    if (m_view) {
        m_view->setPixelScale(_pixelsPerPoint);
    }

    for (auto& style : m_scene->styles()) {
        style->setPixelScale(_pixelsPerPoint);
    }

}

void handleTapGesture(float _posX, float _posY) {

    m_inputHandler->handleTapGesture(_posX, _posY);

}

void handleDoubleTapGesture(float _posX, float _posY) {

    m_inputHandler->handleDoubleTapGesture(_posX, _posY);

}

void handlePanGesture(float _startX, float _startY, float _endX, float _endY) {

    m_inputHandler->handlePanGesture(_startX, _startY, _endX, _endY);

}

void handlePinchGesture(float _posX, float _posY, float _scale, float _velocity) {

    m_inputHandler->handlePinchGesture(_posX, _posY, _scale, _velocity);

}

void handleRotateGesture(float _posX, float _posY, float _radians) {

    m_inputHandler->handleRotateGesture(_posX, _posY, _radians);

}

void handleShoveGesture(float _distance) {

    m_inputHandler->handleShoveGesture(_distance);

}

void setDebugFlag(DebugFlags _flag, bool _on) {

    g_flags.set(_flag, _on);
    m_view->setZoom(m_view->getZoom()); // Force the view to refresh

}

bool getDebugFlag(DebugFlags _flag) {

    return g_flags.test(_flag);

}

void toggleDebugFlag(DebugFlags _flag) {

    g_flags.flip(_flag);
    m_view->setZoom(m_view->getZoom()); // Force the view to refresh

}

void setupGL() {

    logMsg("setup GL\n");

    if (m_tileManager) {
        m_tileManager->clearTileSets();

        for (auto& style : m_scene->styles()) {
           style->notifyGLContextLost();
        }
    }

    // The OpenGL context has been destroyed since the last time resources were created,
    // so we invalidate all data that depends on OpenGL object handles.

    // ShaderPrograms are invalidated and immediately rebuilt
    ShaderProgram::invalidateAllPrograms();

    // Buffer objects are invalidated and re-uploaded the next time they are used
    VboMesh::invalidateAllVBOs();

    // Texture objects are invalidated and re-uploaded the next time they are updated
    Texture::invalidateAllTextures();

    // Reconfigure the render states
    RenderState::configure();

    Primitives::setColor(0xffffff);
}

}
<commit_msg>Add GL error checking to setupGL<commit_after>#include "tangram.h"

#include "platform.h"
#include "scene/scene.h"
#include "scene/sceneLoader.h"
#include "style/style.h"
#include "text/fontContext.h"
#include "labels/labels.h"
#include "tile/tileManager.h"
#include "tile/tile.h"
#include "gl/error.h"
#include "gl/shaderProgram.h"
#include "scene/skybox.h"
#include "view/view.h"
#include "gl/renderState.h"
#include "gl/primitives.h"
#include "util/inputHandler.h"
#include <memory>
#include <cmath>
#include <bitset>

namespace Tangram {

std::unique_ptr<TileManager> m_tileManager;
std::shared_ptr<Scene> m_scene;
std::shared_ptr<View> m_view;
std::unique_ptr<Labels> m_labels;
std::shared_ptr<FontContext> m_ftContext;
std::unique_ptr<Skybox> m_skybox;
std::unique_ptr<InputHandler> m_inputHandler;

static float g_time = 0.0;
static std::bitset<8> g_flags = 0;

void initialize(const char* _scenePath) {

    logMsg("initialize\n");

    if (!m_tileManager) {

        // Create view
        m_view = std::make_shared<View>();

        // Create a scene object
        m_scene = std::make_shared<Scene>();

        // Input handler
        m_inputHandler = std::unique_ptr<InputHandler>(new InputHandler(m_view));

        m_skybox = std::unique_ptr<Skybox>(new Skybox("cubemap.png"));
        m_skybox->init();

        // Create a tileManager
        m_tileManager = TileManager::GetInstance();

        // Pass references to the view and scene into the tile manager
        m_tileManager->setView(m_view);
        m_tileManager->setScene(m_scene);

        // Font and label setup
        m_ftContext = FontContext::GetInstance();
        m_ftContext->addFont("FiraSans-Medium.ttf", "FiraSans");
        m_labels = std::unique_ptr<Labels>(new Labels());

        logMsg("Loading Tangram scene file: %s\n", _scenePath);
        auto sceneString = stringFromResource(_scenePath);

        SceneLoader loader;

        loader.loadScene(sceneString, *m_scene, *m_tileManager, *m_view);

    }

    logMsg("finish initialize\n");

}

void resize(int _newWidth, int _newHeight) {

    logMsg("resize: %d x %d\n", _newWidth, _newHeight);

    glViewport(0, 0, _newWidth, _newHeight);

    if (m_view) {
        m_view->setSize(_newWidth, _newHeight);
    }

    for (auto& style : m_scene->styles()) {
        style->viewportHasChanged();
    }

    Primitives::setResolution(_newWidth, _newHeight);

    while (Error::hadGlError("Tangram::resize()")) {}

}

void update(float _dt) {

    g_time += _dt;

    m_inputHandler->update(_dt);

    m_view->update();

    m_tileManager->updateTileSets();

    if (m_view->changedOnLastUpdate() || m_tileManager->hasTileSetChanged() || m_labels->needUpdate()) {

        auto& tiles = m_tileManager->getVisibleTiles();

        for (const auto& tile : tiles) {
            tile->update(_dt, *m_view);
        }

        m_labels->update(*m_view, _dt, m_scene->styles(), tiles);
    }

    if (m_scene) {
        // Update lights and styles
    }
}

void render() {

    // Set up openGL for new frame
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Loop over all styles
    for (const auto& style : m_scene->styles()) {
        style->onBeginDrawFrame(*m_view, *m_scene);

        // Loop over all tiles in m_tileSet
        for (const auto& tile : m_tileManager->getVisibleTiles()) {
            tile->draw(*style, *m_view);
        }

        style->onEndDrawFrame();
    }

    m_skybox->draw(*m_view);

    m_labels->drawDebug(*m_view);

    while (Error::hadGlError("Tangram::render()")) {}
}

void setPosition(double _lon, double _lat) {

    glm::dvec2 meters = m_view->getMapProjection().LonLatToMeters({ _lon, _lat});
    m_view->setPosition(meters.x, meters.y);
    requestRender();

}

void getPosition(double& _lon, double& _lat) {

    glm::dvec2 meters(m_view->getPosition().x, m_view->getPosition().y);
    glm::dvec2 degrees = m_view->getMapProjection().MetersToLonLat(meters);
    _lon = degrees.x;
    _lat = degrees.y;

}

void setZoom(float _z) {

    m_view->setZoom(_z);
    requestRender();

}

float getZoom() {

    return m_view->getZoom();

}

void setRotation(float _radians) {

    m_view->setRoll(_radians);
    requestRender();

}

float getRotation() {

    return m_view->getRoll();

}

void setTilt(float _radians) {

    m_view->setPitch(_radians);
    requestRender();

}

float getTilt() {

    return m_view->getPitch();

}

void screenToWorldCoordinates(double& _x, double& _y) {

    float screenX = _x, screenY = _y;
    m_view->screenToGroundPlane(screenX, screenY);
    glm::dvec2 meters(screenX + m_view->getPosition().x, screenY + m_view->getPosition().y);
    glm::dvec2 lonLat = m_view->getMapProjection().MetersToLonLat(meters);
    _x = lonLat.x;
    _y = lonLat.y;

}

void setPixelScale(float _pixelsPerPoint) {

    if (m_view) {
        m_view->setPixelScale(_pixelsPerPoint);
    }

    for (auto& style : m_scene->styles()) {
        style->setPixelScale(_pixelsPerPoint);
    }

}

void handleTapGesture(float _posX, float _posY) {

    m_inputHandler->handleTapGesture(_posX, _posY);

}

void handleDoubleTapGesture(float _posX, float _posY) {

    m_inputHandler->handleDoubleTapGesture(_posX, _posY);

}

void handlePanGesture(float _startX, float _startY, float _endX, float _endY) {

    m_inputHandler->handlePanGesture(_startX, _startY, _endX, _endY);

}

void handlePinchGesture(float _posX, float _posY, float _scale, float _velocity) {

    m_inputHandler->handlePinchGesture(_posX, _posY, _scale, _velocity);

}

void handleRotateGesture(float _posX, float _posY, float _radians) {

    m_inputHandler->handleRotateGesture(_posX, _posY, _radians);

}

void handleShoveGesture(float _distance) {

    m_inputHandler->handleShoveGesture(_distance);

}

void setDebugFlag(DebugFlags _flag, bool _on) {

    g_flags.set(_flag, _on);
    m_view->setZoom(m_view->getZoom()); // Force the view to refresh

}

bool getDebugFlag(DebugFlags _flag) {

    return g_flags.test(_flag);

}

void toggleDebugFlag(DebugFlags _flag) {

    g_flags.flip(_flag);
    m_view->setZoom(m_view->getZoom()); // Force the view to refresh

}

void setupGL() {

    logMsg("setup GL\n");

    if (m_tileManager) {
        m_tileManager->clearTileSets();

        for (auto& style : m_scene->styles()) {
           style->notifyGLContextLost();
        }
    }

    // The OpenGL context has been destroyed since the last time resources were created,
    // so we invalidate all data that depends on OpenGL object handles.

    // ShaderPrograms are invalidated and immediately rebuilt
    ShaderProgram::invalidateAllPrograms();

    // Buffer objects are invalidated and re-uploaded the next time they are used
    VboMesh::invalidateAllVBOs();

    // Texture objects are invalidated and re-uploaded the next time they are updated
    Texture::invalidateAllTextures();

    // Reconfigure the render states
    RenderState::configure();

    Primitives::setColor(0xffffff);

    while (Error::hadGlError("Tangram::setupGL()")) {}
}

}
<|endoftext|>


<commit_before>/**
 * This file is part of the CernVM File System.
 */
#include "cvmfs_config.h"
#include "cache_ram.h"

#include <errno.h>

#include <new>

#include "smalloc.h"
#include "util/posix.h"
#include "util_concurrency.h"

using namespace std;  // NOLINT

namespace cache {

int RamCacheManager::AddFd(const ReadOnlyFd &fd) {
  unsigned i = 0;
  for ( ; i < open_fds_.size(); ++i) {
    if (open_fds_[i].handle == -1) {
      open_fds_[i] = fd;
      return i;
    }
  }
  open_fds_.push_back(fd);
  return i;
}

RamCacheManager::RamCacheManager() {
  int retval = pthread_rwlock_init(&rwlock_, NULL);
  assert(retval == 0);
}

RamCacheManager::~RamCacheManager() {
  pthread_rwlock_destroy(&rwlock_);
}

bool RamCacheManager::AcquireQuotaManager(QuotaManager *quota_mgr) {
  return false;
}

int RamCacheManager::Open(const shash::Any &id) {
  // TODO(jblomer): get handle, size from kv store
  ReadOnlyFd fd(0, 0);

  WriteLockGuard guard(rwlock_);
  return AddFd(fd);
}

int64_t RamCacheManager::GetSize(int fd) {
  ReadLockGuard guard(rwlock_);
  if (!IsValid(fd))
    return -EBADFD;
  return open_fds_[fd].size;
}

int RamCacheManager::Close(int fd) {
  bool sweep_tail = false;
  {
    ReadLockGuard guard(rwlock_);
    if (!IsValid(fd))
      return -EBADFD;
    // TODO(jblomer): KvStore
    open_fds_[fd].handle = -1;
    sweep_tail = (static_cast<unsigned>(fd) == (open_fds_.size() - 1));
  }

  if (sweep_tail) {
    WriteLockGuard guard(rwlock_);
    unsigned last_good_idx = open_fds_.size() - 1;
    while (open_fds_[last_good_idx].handle < 0)
      last_good_idx--;
    open_fds_.resize(last_good_idx + 1);
  }

  return 0;
}

int64_t RamCacheManager::Pread(
  int fd,
  void *buf,
  uint64_t size,
  uint64_t offset)
{
  return -EIO;
}

int RamCacheManager::Dup(int fd) {
  ReadOnlyFd file_descriptor;
  {
    ReadLockGuard guard(rwlock_);
    if (!IsValid(fd))
      return -EBADFD;
    file_descriptor = open_fds_[fd];
  }

  // TODO(jblomer): increase link count in kv store
  WriteLockGuard guard(rwlock_);
  return AddFd(file_descriptor);
}

/**
 * For a RAM cache, read-ahead is a no-op.
 */
int RamCacheManager::Readahead(int fd) {
  ReadLockGuard guard(rwlock_);
  if (!IsValid(fd))
    return -EBADFD;
  return 0;
}

int RamCacheManager::StartTxn(const shash::Any &id, uint64_t size, void *txn) {
  Transaction *transaction = new (txn) Transaction();
  transaction->id = id;
  transaction->pos = 0;
  transaction->expected_size = size;
  transaction->size = (size == kSizeUnknown) ? kPageSize : size;
  if (transaction->size) {
    transaction->buffer = smmap(transaction->size);
  }
  return 0;
}

void RamCacheManager::CtrlTxn(
  const string &description,
  const ObjectType type,
  const int flags,
  void *txn)
{
}

int64_t RamCacheManager::Write(const void *buf, uint64_t size, void *txn) {
  return -EIO;
}

int RamCacheManager::Reset(void *txn) {
  Transaction *transaction = reinterpret_cast<Transaction *>(txn);
  transaction->pos = 0;
  return 0;
}

int RamCacheManager::OpenFromTxn(void *txn) {
  Transaction *transaction = reinterpret_cast<Transaction *>(txn);
  int64_t handle = CommitToKvStore(transaction);
  if (handle < 0)
    return handle;
  ReadOnlyFd file_descriptor(handle, transaction->pos);

  WriteLockGuard guard(rwlock_);
  return AddFd(file_descriptor);
}

int RamCacheManager::AbortTxn(void *txn) {
  Transaction *transaction = reinterpret_cast<Transaction *>(txn);
  if (transaction->buffer)
    free(transaction->buffer);
  return 0;
}

int RamCacheManager::CommitTxn(void *txn) {
  Transaction *transaction = reinterpret_cast<Transaction *>(txn);
  int retval = CommitToKvStore(transaction);
  return retval;
}

int64_t RamCacheManager::CommitToKvStore(Transaction *transaction) {
  if (transaction->handle >= 0)
    return transaction->handle;

  // TODO(jblomer): commit transaction in kv store
  transaction->handle = 0;
  if (transaction->buffer) {
    free(transaction->buffer);
    transaction->buffer = NULL;
  }
  return transaction->handle;
}

}  // namespace cache
<commit_msg>fix errno constant name<commit_after>/**
 * This file is part of the CernVM File System.
 */
#include "cvmfs_config.h"
#include "cache_ram.h"

#include <errno.h>

#include <new>

#include "smalloc.h"
#include "util/posix.h"
#include "util_concurrency.h"

using namespace std;  // NOLINT

namespace cache {

int RamCacheManager::AddFd(const ReadOnlyFd &fd) {
  unsigned i = 0;
  for ( ; i < open_fds_.size(); ++i) {
    if (open_fds_[i].handle == -1) {
      open_fds_[i] = fd;
      return i;
    }
  }
  open_fds_.push_back(fd);
  return i;
}

RamCacheManager::RamCacheManager() {
  int retval = pthread_rwlock_init(&rwlock_, NULL);
  assert(retval == 0);
}

RamCacheManager::~RamCacheManager() {
  pthread_rwlock_destroy(&rwlock_);
}

bool RamCacheManager::AcquireQuotaManager(QuotaManager *quota_mgr) {
  return false;
}

int RamCacheManager::Open(const shash::Any &id) {
  // TODO(jblomer): get handle, size from kv store
  ReadOnlyFd fd(0, 0);

  WriteLockGuard guard(rwlock_);
  return AddFd(fd);
}

int64_t RamCacheManager::GetSize(int fd) {
  ReadLockGuard guard(rwlock_);
  if (!IsValid(fd))
    return -EBADF;
  return open_fds_[fd].size;
}

int RamCacheManager::Close(int fd) {
  bool sweep_tail = false;
  {
    ReadLockGuard guard(rwlock_);
    if (!IsValid(fd))
      return -EBADF;
    // TODO(jblomer): KvStore
    open_fds_[fd].handle = -1;
    sweep_tail = (static_cast<unsigned>(fd) == (open_fds_.size() - 1));
  }

  if (sweep_tail) {
    WriteLockGuard guard(rwlock_);
    unsigned last_good_idx = open_fds_.size() - 1;
    while (open_fds_[last_good_idx].handle < 0)
      last_good_idx--;
    open_fds_.resize(last_good_idx + 1);
  }

  return 0;
}

int64_t RamCacheManager::Pread(
  int fd,
  void *buf,
  uint64_t size,
  uint64_t offset)
{
  return -EIO;
}

int RamCacheManager::Dup(int fd) {
  ReadOnlyFd file_descriptor;
  {
    ReadLockGuard guard(rwlock_);
    if (!IsValid(fd))
      return -EBADF;
    file_descriptor = open_fds_[fd];
  }

  // TODO(jblomer): increase link count in kv store
  WriteLockGuard guard(rwlock_);
  return AddFd(file_descriptor);
}

/**
 * For a RAM cache, read-ahead is a no-op.
 */
int RamCacheManager::Readahead(int fd) {
  ReadLockGuard guard(rwlock_);
  if (!IsValid(fd))
    return -EBADF;
  return 0;
}

int RamCacheManager::StartTxn(const shash::Any &id, uint64_t size, void *txn) {
  Transaction *transaction = new (txn) Transaction();
  transaction->id = id;
  transaction->pos = 0;
  transaction->expected_size = size;
  transaction->size = (size == kSizeUnknown) ? kPageSize : size;
  if (transaction->size) {
    transaction->buffer = smmap(transaction->size);
  }
  return 0;
}

void RamCacheManager::CtrlTxn(
  const string &description,
  const ObjectType type,
  const int flags,
  void *txn)
{
}

int64_t RamCacheManager::Write(const void *buf, uint64_t size, void *txn) {
  return -EIO;
}

int RamCacheManager::Reset(void *txn) {
  Transaction *transaction = reinterpret_cast<Transaction *>(txn);
  transaction->pos = 0;
  return 0;
}

int RamCacheManager::OpenFromTxn(void *txn) {
  Transaction *transaction = reinterpret_cast<Transaction *>(txn);
  int64_t handle = CommitToKvStore(transaction);
  if (handle < 0)
    return handle;
  ReadOnlyFd file_descriptor(handle, transaction->pos);

  WriteLockGuard guard(rwlock_);
  return AddFd(file_descriptor);
}

int RamCacheManager::AbortTxn(void *txn) {
  Transaction *transaction = reinterpret_cast<Transaction *>(txn);
  if (transaction->buffer)
    free(transaction->buffer);
  return 0;
}

int RamCacheManager::CommitTxn(void *txn) {
  Transaction *transaction = reinterpret_cast<Transaction *>(txn);
  int retval = CommitToKvStore(transaction);
  return retval;
}

int64_t RamCacheManager::CommitToKvStore(Transaction *transaction) {
  if (transaction->handle >= 0)
    return transaction->handle;

  // TODO(jblomer): commit transaction in kv store
  transaction->handle = 0;
  if (transaction->buffer) {
    free(transaction->buffer);
    transaction->buffer = NULL;
  }
  return transaction->handle;
}

}  // namespace cache
<|endoftext|>


<commit_before>#ifndef CONTEXT_HPP_
#define CONTEXT_HPP_

#include <string>
#include <atomic>
#include <memory>
#include <thread>
#include <cstdio>

std::string runCommand(std::string command) {
	std::FILE* pipe = popen(command.c_str(), "r");

	if(!pipe) return "";

	char buffer[128];

	std::string result;

	while(!std::feof(pipe)) {
		std::fgets(buffer, sizeof(buffer), pipe);
		result += buffer;
	}
	pclose(pipe);
	return result;
}

class Context: std::enable_shared_from_this<Context> {
	std::atomic_bool isRunning;
	std::string cwd;

	std::atomic<std::shared_ptr<std::string>> currentResult;

public:

	Context() {
		isRunning.store(false);
		currentResult.store(std::make_shared<std::string>(""));
	}

	void setCwd(std::string c) { cwd = std::move(c); }
	const std::string& getCwd() const { return cwd; }

	void run() {
		isRunning = true;
		std::thread t(
				[&](){
					currentResult.store(std::make_shared<std::string>(runCommand("ls -la")));
				}
		);
	}

	void stop() {
		isRunning = false;
	}

};

#endif /* CONTEXT_HPP_ */
<commit_msg>Add getResult to Context<commit_after>#ifndef CONTEXT_HPP_
#define CONTEXT_HPP_

#include <string>
#include <atomic>
#include <memory>
#include <thread>
#include <cstdio>

std::string runCommand(std::string command) {
	std::FILE* pipe = popen(command.c_str(), "r");

	if(!pipe) return "";

	char buffer[128];

	std::string result;

	while(!std::feof(pipe)) {
		std::fgets(buffer, sizeof(buffer), pipe);
		result += buffer;
	}
	pclose(pipe);
	return result;
}

class Context: std::enable_shared_from_this<Context> {
	std::atomic_bool isRunning;
	std::string cwd;

	std::atomic<std::shared_ptr<std::string>> currentResult;

public:

	Context() {
		isRunning.store(false);
		currentResult.store(std::make_shared<std::string>(""));
	}

	void setCwd(std::string c) { cwd = std::move(c); }
	const std::string& getCwd() const { return cwd; }

	void run() {
		isRunning = true;
		std::thread t(
				[&](){
					currentResult.store(std::make_shared<std::string>(runCommand("ls -la")));
				}
		);
	}

	void stop() {
		isRunning = false;
	}

	std::string getResult() const {
		return *currentResult.load();
	}

};

#endif /* CONTEXT_HPP_ */
<|endoftext|>


<commit_before>#ifndef __WORLD_HPP_INCLUDED
#define __WORLD_HPP_INCLUDED

#include "globals.hpp"
#include "model_common_functions.hpp"
#include "model_templates.hpp"

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h> // GLfloat, GLuint etc.
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp> // glm
#endif

// Include standard headers
#include <iostream>
#include <vector>    // std::vector
#include <queue>     // std::queue

// `World`, `Shader`, `Material`, `Species`, `Object`.
// `World` must be created before any `Shader`. `parent_pointer` must be given to each `Shader`.
// `Shader` must be created before any `Material`. `parent_pointer` must be given to each `Material`.
// `Material` must be created before any `Species`. `parent_pointer` must be given to each `Species`.
// `Species` must be create before any `Object` of that `Species`. `parent_pointer` must be given to each `Object` of the `Species`.
//
//
// Hierarchy for regular objects (including world species):
//
//     World
//       ^
//    Shader
//       ^
//    Material
//       ^
//    Species
//       ^
//    Object
//
//
// Hierarchy for glyph (character) objects:
//
//     World
//       ^
//    Shader
//       ^
//    Material
//       ^
//     Font
//       ^
//     Glyph
//       ^
//    Object
//
//
// Deleting a `World` also deletes all shaders, textures, species and objects that are binded to the same World.
// Deleting a `Shader` also deletes all textures, species and objects that are binded to the same Shader.
// Deleting a `Material` also deletes all species and objects that are binded to the same Material.
// Deleting a `Species` also deletes all objects that are binded to the same Species.
// Deleting an `Object` only deletes the object.

// Characteristics of object type graphs:
// 1. Each object must be an undirected graph.
// 2. Each edge must be a link in the graph.
// 3. The faces of each object must form a closed surface. The only exception is the terrain object, which may have borders.
//
// Modifying object type graphs:
// 1. Translation of a vertex does not require changes in any other nodes of the graph.
// 2. Adding a vertex always requires changes in some other nodes of the graph (unless the graph is empty before adding the vertex).
// 3. Deleting a vertex always requires deletion of edges from some other nodes of the graph (unless the vertex is the only vertex of the graph).
// 4. Deleting a vertex or vertices usually also requires appropriate vertex additions. These changes are called 'complex modifications'.
//
// Adding a vertex or several vertices:
// 1. The new edges must be connected to the existing graph with appropriate links.
// 2. Each new face must be a triangle.
//
// Deleting a vertex or several vertices:
// 1. When a vertex or several vertices are deleted, their links must be deleted too (`Node` destructor handles this).
// 2. If the vertex to be deleted is on the border of a [terrain] object, it can be deleted.
// 3. If the vertices that are neighbors to the vertex to be deleted form only triangeles, the vertex can be deleted without vertex additions.
// 4. Otherwise the vertex cannot be deleted without appropriate vertex and edge additions.
//
// Complex modifications:
// 1. In complex modifications one or more vertices and edges are deleted and one or more vertices and edges are added.
// 2. Complex modifications may also change the topology of the object (tunnels, arcs, etc.).
// 3. If a complex modification causes splitting the object in two or more pieces, each piece becomes a separate object.
// 4. If the splitted object is a terrain object, then the lowest vertex (any vertex with smallest y-coordinate) of each piece is searched and the
//    y-coordinates of these are compared. The piece with the smallest y-coordinate (lowest altitude) remains terrain, other pieces become
//    regular objects. The pieces that become regular objects will be subject to gravity the same way as any regular object.

namespace model
{
    class Shader;

    class World
    {
        public:
            // constructor.
            World();

            // destructor.
            ~World();

            // this method renders the entire world, one shader at a time.
            void render();

            friend class Shader;
            friend class Species;

        private:
            // this method sets a shader pointer.
            void set_shader_pointer(GLuint childID, void* parent_pointer);

            // this method sets a world species pointer.
            void set_terrain_species_pointer(void* terrain_species_pointer);

            void compute_matrices_from_inputs();

            void* terrain_species_pointer;              // pointer to world species (used in collision detection).

            std::vector<void*> shader_pointer_vector;
            std::queue<GLuint> free_shaderID_queue;
    };
}

#endif
<commit_msg>Muokattu kommentteja.<commit_after>#ifndef __WORLD_HPP_INCLUDED
#define __WORLD_HPP_INCLUDED

#include "globals.hpp"
#include "model_common_functions.hpp"
#include "model_templates.hpp"

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h> // GLfloat, GLuint etc.
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp> // glm
#endif

// Include standard headers
#include <iostream>
#include <vector>    // std::vector
#include <queue>     // std::queue

// `World`, `Shader`, `Material`, `Species`, `Object`.
// `World`, `Shader`, `Material`, `Font`, `Glyph`, `Object`.
// `World` must be created before any `Shader`. `parent_pointer` must be given to each `Shader`.
// `Shader` must be created before any `Material`. `parent_pointer` must be given to each `Material`.
// `Material` must be created before any `Species`. `parent_pointer` must be given to each `Species`.
// `Species` must be create before any `Object` of that `Species`. `parent_pointer` must be given to each `Object` of the `Species`.
//
//
// Hierarchy for regular objects (including terrain species):
//
//     World
//       ^
//     Shader
//       ^
//    Material
//       ^
//    Species
//       ^
//     Object
//
//
// Hierarchy for glyph (character) objects:
//
//     World
//       ^
//     Shader
//       ^
//    Material
//       ^
//      Font
//       ^
//     Glyph
//       ^
//     Object
//
//
// Deleting a `World` also deletes all shaders, materials, species, fonts, glyphs and objects that are binded to the same World.
// Deleting a `Shader` also deletes all materials, species, fonts, glyphs and objects that are binded to the same Shader.
// Deleting a `Material` also deletes all species, fonts, glyphs and objects that are binded to the same Material.
// Deleting a `Species` also deletes all objects that are binded to the same Species.
// Deleting an `Object` only deletes the object.

// Characteristics of object type graphs:
// 1. Each object must be an undirected graph.
// 2. Each edge must be a link in the graph.
// 3. The faces of each object must form a closed surface. The only exception is the terrain object, which may have borders.
//
// Modifying object type graphs:
// 1. Translation of a vertex does not require changes in any other nodes of the graph.
// 2. Adding a vertex always requires changes in some other nodes of the graph (unless the graph is empty before adding the vertex).
// 3. Deleting a vertex always requires deletion of edges from some other nodes of the graph (unless the vertex is the only vertex of the graph).
// 4. Deleting a vertex or vertices usually also requires appropriate vertex additions. These changes are called 'complex modifications'.
//
// Adding a vertex or several vertices:
// 1. The new edges must be connected to the existing graph with appropriate links.
// 2. Each new face must be a triangle.
//
// Deleting a vertex or several vertices:
// 1. When a vertex or several vertices are deleted, their links must be deleted too (`Node` destructor handles this).
// 2. If the vertex to be deleted is on the border of a [terrain] object, it can be deleted.
// 3. If the vertices that are neighbors to the vertex to be deleted form only triangeles, the vertex can be deleted without vertex additions.
// 4. Otherwise the vertex cannot be deleted without appropriate vertex and edge additions.
//
// Complex modifications:
// 1. In complex modifications one or more vertices and edges are deleted and one or more vertices and edges are added.
// 2. Complex modifications may also change the topology of the object (tunnels, arcs, etc.).
// 3. If a complex modification causes splitting the object in two or more pieces, each piece becomes a separate object.
// 4. If the splitted object is a terrain object, then the lowest vertex (any vertex with smallest y-coordinate) of each piece is searched and the
//    y-coordinates of these are compared. The piece with the smallest y-coordinate (lowest altitude) remains terrain, other pieces become
//    regular objects. The pieces that become regular objects will be subject to gravity the same way as any regular object.

namespace model
{
    class Shader;

    class World
    {
        public:
            // constructor.
            World();

            // destructor.
            ~World();

            // this method renders the entire world, one shader at a time.
            void render();

            friend class Shader;
            friend class Species;

        private:
            // this method sets a shader pointer.
            void set_shader_pointer(GLuint childID, void* parent_pointer);

            // this method sets a world species pointer.
            void set_terrain_species_pointer(void* terrain_species_pointer);

            void compute_matrices_from_inputs();

            void* terrain_species_pointer;              // pointer to world species (used in collision detection).

            std::vector<void*> shader_pointer_vector;
            std::queue<GLuint> free_shaderID_queue;
    };
}

#endif
<|endoftext|>


<commit_before>//Graph implementation
//Author: Ginevra Gaudioso
//CS345 assignment 6
//May 5, 2016

#include "Graph.h"

#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <math.h>
#include <cfloat>

#define X 0     //x coord position
#define Y 1     //y coord position
#define VIS 2   //visited flag position

using namespace std;

//constructor of Graph
Graph::Graph(char* path) throw() {

	//1. open input file, which is assumed to be in the format of a280.tsp
	ifstream graphFile; //create input stream
	graphFile.open(path,ios::in); //use stream to read the file

	if (graphFile.is_open()) {
		string line;

		//2. get number of nodes in the graph
		int size=0; //initialize size
		while (getline(graphFile, line)) {
			if (line.length()>9 && (line.substr(0,9)).compare("DIMENSION")==0) {
				//save size = number of nodes in the graph, as integer, and leave
				size = atoi(line.substr(11,line.length()-11).c_str());
				break;
			}
		}
		if (size==0) { //size was not set, thus file format must be wrong
			cout << "no dimension specified in file" << endl;
			throw;
		}

		//3. allocate array to store nodes and visited, and save size
		array_of_nodes = new int*[size+1]; //+1 to correct 0 base to 1 base
		num_nodes = size;

		//4. fill in array with coordinates
		while (getline(graphFile, line)) {
			if (line.length()>3 && line[2]<='9' && line[2]>='0') {
				int index = atoi(line.substr(0,3).c_str()); //index is node number, which will go from 1 to size
				int x = atoi(line.substr(4,3).c_str()); //get x coordinate
				int y = atoi(line.substr(8,3).c_str()); //get y coordinate
				array_of_nodes[index] = new int[3]; //3 = x coord, y coord, visited flag
				array_of_nodes[index][X] = x; //save x coordinate
				array_of_nodes[index][Y] = y; //save y coordinate
				array_of_nodes[index][VIS] = 0; //not visited
			}
		}
	}
	else { //file cannot be read
		cout << "cannot read file" << endl;
		throw;
	}
	//5. done with file
	graphFile.close();

	//Graph is stored as array <node number> <xcoord> <ycoord> <visited>
}

//returns size of graph as number of nodes
int Graph::getsize() {
	return num_nodes;
}

//returns start node of graph
int Graph::getstart() {
	return 1;
}

//finds the distance between node a and b
double Graph::getdistance(int a, int b) {
	if (a<1 || a>=num_nodes-1 || b<1 || b>=num_nodes-1) //not a valid node for this graph
		return -1;
	else {
		int xdist = array_of_nodes[a][X]-array_of_nodes[b][X];
		int ydist = array_of_nodes[a][Y]-array_of_nodes[b][Y];
		return sqrt(pow(xdist,2)+pow(ydist,2));
	}
}

//gets closest non visited node from a
int Graph::getclosest(int a) {
	if (a<1 || a>num_nodes) //not a valid node for this graph
			return -1;
	array_of_nodes[a][VIS] = 1; //starting point is visited
	double mindist = DBL_MAX; //initialize minimum
	int minnode = -1; //initialize to negative as flag
	for (int i=1; i<=num_nodes;i++){
		if (array_of_nodes[i][VIS]==0) { //not visited
			double dist = getdistance(a,i); //get distance from a to i
			if (dist < mindist)  {
				mindist = dist; //update min dist
				minnode = i; //save closest node
			}
		}
	}
	if (minnode != -1) array_of_nodes[minnode][VIS] = 1; //set end point to visited
	return minnode;
}

//get cost of tour
double Graph::getcost(vector<int> tour) {
	if (tour.empty()) //invalid input
		return -1;
	vector<int>::iterator it = tour.begin(); //iterator on tour vector
	int start = *it; //save starting point
	int a = start;
	int b = -1;
	double cost = 0; //returned cost
	it++;
	for (;it!=tour.end();++it){
		b = *it;
		cost += getdistance(a,b); //add up
		a = b;
	}
	cost += getdistance(b,start); //add up last edge
	return cost;
}

//destructor of Graph, called with delete
Graph::~Graph() {
	//need to release memory of array
	for (int i=1;i<=num_nodes;i++)
		delete[] array_of_nodes[i]; //free each row
	delete[] array_of_nodes; //free array
}

<commit_msg>bug fix<commit_after>//Graph implementation
//Author: Ginevra Gaudioso
//CS345 assignment 6
//May 5, 2016

#include "Graph.h"

#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <math.h>
#include <cfloat>

#define X 0     //x coord position
#define Y 1     //y coord position
#define VIS 2   //visited flag position

using namespace std;

//constructor of Graph
Graph::Graph(char* path) throw() {

	//1. open input file, which is assumed to be in the format of a280.tsp
	ifstream graphFile; //create input stream
	graphFile.open(path,ios::in); //use stream to read the file

	if (graphFile.is_open()) {
		string line;

		//2. get number of nodes in the graph
		int size=0; //initialize size
		while (getline(graphFile, line)) {
			if (line.length()>9 && (line.substr(0,9)).compare("DIMENSION")==0) {
				//save size = number of nodes in the graph, as integer, and leave
				size = atoi(line.substr(11,line.length()-11).c_str());
				break;
			}
		}
		if (size==0) { //size was not set, thus file format must be wrong
			cout << "no dimension specified in file" << endl;
			throw;
		}

		//3. allocate array to store nodes and visited, and save size
		array_of_nodes = new int*[size+1]; //+1 to correct 0 base to 1 base
		num_nodes = size;

		//4. fill in array with coordinates
		while (getline(graphFile, line)) {
			if (line.length()>3 && line[2]<='9' && line[2]>='0') {
				int index = atoi(line.substr(0,3).c_str()); //index is node number, which will go from 1 to size
				int x = atoi(line.substr(4,3).c_str()); //get x coordinate
				int y = atoi(line.substr(8,3).c_str()); //get y coordinate
				array_of_nodes[index] = new int[3]; //3 = x coord, y coord, visited flag
				array_of_nodes[index][X] = x; //save x coordinate
				array_of_nodes[index][Y] = y; //save y coordinate
				array_of_nodes[index][VIS] = 0; //not visited
			}
		}
	}
	else { //file cannot be read
		cout << "cannot read file" << endl;
		throw;
	}
	//5. done with file
	graphFile.close();

	//Graph is stored as array <node number> <xcoord> <ycoord> <visited>
}

//returns size of graph as number of nodes
int Graph::getsize() {
	return num_nodes;
}

//returns start node of graph
int Graph::getstart() {
//here I decided to have an arbitrary start, instead of checking which starting point would provide the best greedy solution
//It is possible to add a for loop into main "for i from getstart to getsize" and then pick the least cost route, but that adds an order to the complexity
	return 1;
}

//finds the distance between node a and b
double Graph::getdistance(int a, int b) {
	if (a<1 || a>num_nodes || b<1 || b>num_nodes) //not a valid node for this graph
		return -1;
	else {
		int xdist = array_of_nodes[a][X]-array_of_nodes[b][X];
		int ydist = array_of_nodes[a][Y]-array_of_nodes[b][Y];
		return sqrt(pow(xdist,2)+pow(ydist,2));
	}
}

//gets closest non visited node from a
int Graph::getclosest(int a) {
	if (a<1 || a>num_nodes) //not a valid node for this graph
			return -1;
	array_of_nodes[a][VIS] = 1; //starting point is visited
	double mindist = DBL_MAX; //initialize minimum
	int minnode = -1; //initialize to negative as flag
	for (int i=1; i<=num_nodes;i++){
		if (array_of_nodes[i][VIS]==0) { //not visited
			double dist = getdistance(a,i); //get distance from a to i
			if (dist <= mindist)  {
				mindist = dist; //update min dist
				minnode = i; //save closest node
			}
		}
	}
	if (minnode != -1) array_of_nodes[minnode][VIS] = 1; //set end point to visited
	return minnode;
}

//get cost of tour
double Graph::getcost(vector<int> tour) {
	if (tour.empty()) //invalid input
		return -1;
	vector<int>::iterator it = tour.begin(); //iterator on tour vector
	int start = *it; //save starting point
	int a = start;
	int b = -1;
	double cost = 0; //returned cost
	it++;
	for (;it!=tour.end();++it){
		b = *it;
		cost += getdistance(a,b); //add up
		a = b;
	}
	cost += getdistance(b,start); //add up last edge
	return cost;
}

//destructor of Graph, called with delete
Graph::~Graph() {
	//need to release memory of array
	for (int i=1;i<=num_nodes;i++)
		delete[] array_of_nodes[i]; //free each row
	delete[] array_of_nodes; //free array
}

<|endoftext|>


<commit_before>#ifndef TIME_LIMITED_HPP_INC
#define TIME_LIMITED_HPP_INC

/**
 @file time_limited.hpp
 @author François Becker

MIT License

Copyright (c) 2016-2017 François Becker

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include "JuceHeader.h"

#include "build_info.hpp"

#include "time_utils.hpp"

/**
 @class TimeLimitedFromBuild
 */
template <int DAYSAFTERBUILD>
class TimeLimitedFromBuild
{
public:
    TimeLimitedFromBuild()
    : mLimit(tu::timeFromStringDate(getBuildInfo().mDate.c_str()) + DAYSAFTERBUILD * 24 * 3600)
    {
    }

    String getTimeLimit() const
    {
        return std::ctime(&mLimit);
    }

    bool isOutdated() const
    {
        std::time_t lNow = std::time(nullptr);
        return difftime(lNow, mLimit) > 0.;
    }

private:
    std::time_t mLimit;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TimeLimitedFromBuild)
};

/**
 @class TimeLimitedFromFirstRun
 */
template <int DAYSAFTERFIRSTRUN>
class TimeLimitedFromFirstRun
{
public:
    TimeLimitedFromFirstRun(const String& pCompanyName, const String& pSKU, const String& pVersion, bool pCommonToAllUsers)
    : mLimit()
    {
        String lVersion(pVersion.replaceCharacters(".", "p"));

        PropertiesFile::Options lOptions;
        lOptions.applicationName = String(".") + pSKU;
        lOptions.filenameSuffix = "bin";
        lOptions.folderName = pCompanyName;
        lOptions.osxLibrarySubFolder = "Application Support";
        lOptions.commonToAllUsers = pCommonToAllUsers;
        lOptions.ignoreCaseOfKeyNames = false;
        lOptions.doNotSave = false;
        lOptions.millisecondsBeforeSaving = 0;
        lOptions.storageFormat = PropertiesFile::storeAsCompressedBinary;
        ScopedPointer<PropertiesFile> lSettings = new PropertiesFile(lOptions);

        String lLimitString = lSettings->getValue(lVersion, "");
        if (lLimitString.isEmpty())
        {
            std::time_t lNow = std::time(nullptr);
            mLimit = lNow + DAYSAFTERFIRSTRUN * 24 * 3600;
            lSettings->setValue(lVersion, String((long)mLimit));
        }
        else
        {
            mLimit = (long)lLimitString.getDoubleValue(); // TODO: something more direct
        }
    }

    String getTimeLimit() const
    {
        return std::ctime(&mLimit);
    }

    bool isOutdated() const
    {
        std::time_t lNow = std::time(nullptr);
        return difftime(lNow, mLimit) > 0.;
    }

private:
    std::time_t                   mLimit;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TimeLimitedFromFirstRun)
};

#endif
<commit_msg>TimeLimitedFromBuild: added a caching utility for efficiency<commit_after>#ifndef TIME_LIMITED_HPP_INC
#define TIME_LIMITED_HPP_INC

/**
 @file time_limited.hpp
 @author François Becker

MIT License

Copyright (c) 2016-2017 François Becker

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include "JuceHeader.h"

#include "build_info.hpp"

#include "time_utils.hpp"

/**
 @class TimeLimitedFromBuild
 */
template <int DAYSAFTERBUILD>
class TimeLimitedFromBuild
{
public:
    TimeLimitedFromBuild()
    : mLimit(tu::timeFromStringDate(getBuildInfo().mDate.c_str()) + DAYSAFTERBUILD * 24 * 3600)
    , mIsOutdatedCached(isOutdated())
    {
    }

    String getTimeLimit() const
    {
        return std::ctime(&mLimit);
    }

    bool isOutdated() const
    {
        std::time_t lNow = std::time(nullptr);
        return difftime(lNow, mLimit) > 0.;
    }

    bool isOutdatedCached() const
    {
        return mIsOutdatedCached;
    }

private:
    std::time_t mLimit;
    bool        mIsOutdatedCached;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TimeLimitedFromBuild)
};

/**
 @class TimeLimitedFromFirstRun
 */
template <int DAYSAFTERFIRSTRUN>
class TimeLimitedFromFirstRun
{
public:
    TimeLimitedFromFirstRun(const String& pCompanyName, const String& pSKU, const String& pVersion, bool pCommonToAllUsers)
    : mLimit()
    {
        String lVersion(pVersion.replaceCharacters(".", "p"));

        PropertiesFile::Options lOptions;
        lOptions.applicationName = String(".") + pSKU;
        lOptions.filenameSuffix = "bin";
        lOptions.folderName = pCompanyName;
        lOptions.osxLibrarySubFolder = "Application Support";
        lOptions.commonToAllUsers = pCommonToAllUsers;
        lOptions.ignoreCaseOfKeyNames = false;
        lOptions.doNotSave = false;
        lOptions.millisecondsBeforeSaving = 0;
        lOptions.storageFormat = PropertiesFile::storeAsCompressedBinary;
        ScopedPointer<PropertiesFile> lSettings = new PropertiesFile(lOptions);

        String lLimitString = lSettings->getValue(lVersion, "");
        if (lLimitString.isEmpty())
        {
            std::time_t lNow = std::time(nullptr);
            mLimit = lNow + DAYSAFTERFIRSTRUN * 24 * 3600;
            lSettings->setValue(lVersion, String((long)mLimit));
        }
        else
        {
            mLimit = (long)lLimitString.getDoubleValue(); // TODO: something more direct
        }
    }

    String getTimeLimit() const
    {
        return std::ctime(&mLimit);
    }

    bool isOutdated() const
    {
        std::time_t lNow = std::time(nullptr);
        return difftime(lNow, mLimit) > 0.;
    }

private:
    std::time_t                   mLimit;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TimeLimitedFromFirstRun)
};

#endif
<|endoftext|>