<commit_before>
/*
 * Copyright (c) 2012 Karl N. Redgate
 *
 * 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.
 */

/** \file Neighbor.cc
 * \brief
 *
 */

#include <stdint.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <glob.h>
#include <errno.h>

#include <tcl.h>
#include "tcl_util.h"

#include "logger.h"
#include "util.h"
#include "Neighbor.h"
#include "Interface.h"

/*
 * I do not like this - try to eliminate OS defines
 */
#if defined(__APPLE__) || defined(__darwin__)
/* OSX seems not to define these. */
#ifndef s6_addr16
#define s6_addr16 __u6_addr.__u6_addr16
#endif
#ifndef s6_addr32
#define s6_addr32 __u6_addr.__u6_addr32
#endif
#endif

namespace { int debug = 0; }

/**
 */
void
Network::Node::uuid( UUID& that ) {
    _uuid = that;
    _ordinal = 255;
    valid = true;
    // log_notice( "new node allocated with uuid %s", _uuid.to_s() );
}

/**
 */
void
Network::Node::ordinal( uint8_t value ) {
    _ordinal = value;
    // log_notice( "node%d %s", _ordinal, _uuid.to_s() );
}

/**
 */
bool
Network::Node::operator == ( UUID& that ) {
    return _uuid == that;
}

/**
 */
bool
Network::Node::operator != ( UUID& that ) {
    return _uuid != that;
}

/**
 * Used to iterate through the node list and clear the partner
 * bit in all entries.
 */
class ClearNodePartner : public Network::NodeIterator {
public:
    ClearNodePartner() {}
    virtual ~ClearNodePartner() {}
    virtual int operator() ( Network::Node& node ) {
        if ( node.not_partner() ) return 0;
        log_notice( "clear partner [%s]", node.uuid().to_s() );
        node.clear_partner();
        return 1;
    }
};

/**
 */
Network::Peer::~Peer() {
    if ( _name != NULL ) free( _name );
    _name = NULL;
}

/**
 * This one should be deprecated
 */
Network::Peer::Peer( Network::Node *__node, struct in6_addr *address )
: _node(__node), _ordinal(0), _name(NULL) {
    memcpy( &lladdr, address, sizeof lladdr );
    memset( &neighbor_updated, 0, sizeof neighbor_updated );
}

/**
 */
void
Network::Peer::node( Node *that ) {
    _node = that;

    /*
     * Here we have just discovered a new partner.  If this was the
     * cached partner, then the _node would already be a partner.
     * Since it was not and the neighbor is a partner - it must
     * have been discovered on priv0, which either overrides the
     * cached partner (node replace or the like) or this is the
     * first time we have discovered the partner.  Either way
     * we need to cache the newly discovered partner.
     */
    if ( is_partner() and _node->not_partner() ) {
        _node->make_partner();
        log_notice( "node %s is partner", _node->uuid().to_s() );
    }

    /*
     * Cases that are ignored:
     * peer->not_partner() and _node->not_partner()
     *   -- who cares about this neighbor
     *
     * peer->is_partner() and _node->is_partner()
     *   -- we already have all necessary state
     *
     */

    if ( debug < 2 ) return;
    char buffer[80];
    const char *address_string = inet_ntop(AF_INET6, &lladdr, buffer, sizeof buffer);
    log_notice( "%s at %s is node %s",
                        (_node->is_partner() ? "partner" : "neighbor"),
                        address_string, _node->uuid().to_s() );
}

/**
 */
Network::Node *
Network::Peer::node() const {
    return _node;
}

/**
 * Since this is a sort of allocation method, maybe this should check if
 * already valid and either disallow usage -- or at least report that the
 * address is changing.
 */
void
Network::Peer::address( struct in6_addr *addr ) {
    memcpy( &lladdr, addr, sizeof lladdr );
    valid = true;
    if ( debug < 2 ) return;
    char buffer[80];
    const char *address_string = inet_ntop(AF_INET6, addr, buffer, sizeof buffer);
    log_notice( "new neighbor %s", address_string );
}

/**
 */
void
Network::Peer::set_interface( bool set_private, uint8_t set_ordinal ) {
    _is_private = set_private;
    _ordinal = set_ordinal;
}

/**
 */
void
Network::Peer::set_interface_name( char *name ) {
    if ( name == NULL ) {			// If the new name is NULL...
       if ( _name != NULL ) {			// ...and the Peer had a name...
           free( _name );			//    ...free the old name...
           _name = NULL;			//    ...and invalidate the name.
       }
       return;
    }

    if ( _name != NULL ) {			// If the Peer already has a name...
        if ( strcmp( name, _name ) ) {		// ...and it is *not* the same name...
            free( _name );			//    ...free the old name...
            _name = strdup( name );		//    ...and copy the new name.
        }					// If it *is* the same name, don't do free()/strdup()
    } else {					// If the Peer does not have a name...
        _name = strdup( name );			// ...copy the new name.
    }
}

/**
 */
void
Network::Peer::copy_address( struct in6_addr *address ) const {
    memcpy( address, &lladdr, sizeof lladdr );
}

/**
 */
void
Network::Peer::touch_advertised() {
    gettimeofday( &neighbor_advertised, 0 );
}

/**
 */
void
Network::Peer::touch() {
    gettimeofday( &neighbor_updated, 0 );
}

/**
 */
int
Network::Peer::seconds_since_last_update() const {
    struct timeval now;
    gettimeofday( &now, 0 );
    return now.tv_sec - neighbor_updated.tv_sec;
}

/**
 */
bool
Network::Peer::operator == ( struct in6_addr& that ) {
    if ( that.s6_addr32[0] != lladdr.s6_addr32[0] ) return false;
    if ( that.s6_addr32[1] != lladdr.s6_addr32[1] ) return false;
    if ( that.s6_addr32[2] != lladdr.s6_addr32[2] ) return false;
    if ( that.s6_addr32[3] != lladdr.s6_addr32[3] ) return false;
    return true;
}

/**
 */
bool
Network::Peer::operator != ( struct in6_addr& that ) {
    if ( that.s6_addr32[0] != lladdr.s6_addr32[0] ) return true;
    if ( that.s6_addr32[1] != lladdr.s6_addr32[1] ) return true;
    if ( that.s6_addr32[2] != lladdr.s6_addr32[2] ) return true;
    if ( that.s6_addr32[3] != lladdr.s6_addr32[3] ) return true;
    return false;
}

/**
 */
bool
Network::Peer::has_address( struct in6_addr *address ) {
    if ( address->s6_addr32[0] != lladdr.s6_addr32[0] ) return false;
    if ( address->s6_addr32[1] != lladdr.s6_addr32[1] ) return false;
    if ( address->s6_addr32[2] != lladdr.s6_addr32[2] ) return false;
    if ( address->s6_addr32[3] != lladdr.s6_addr32[3] ) return false;
    return true;
}

/**
 */
static void
construct_remote_interface_name( Network::Peer *neighbor, char *name, int size ) {

    if ( neighbor->name() != NULL ) {
        strncpy( name, neighbor->name(), size );
    } else {
        int ordinal = neighbor->ordinal();
        if ( neighbor->is_private() ) {
            if ( ordinal & 0x40 ) {
                int slot = ( ordinal & 0x3c ) >> 2;
                int port = ( ordinal & 0x03);
                snprintf( name, size, "sync_pci%dp%d", slot, port );
            } else {
                snprintf( name, size, "priv%d", ordinal );
            }
        } else {
            snprintf( name, size, "ibiz%d", ordinal );
        }
    }
}

/**
 */
void
Network::Peer::topology_changed( Network::Monitor *monitor, Network::Interface *interface ) {
    char node_ordinal = (node() == NULL) ? '?' : ('0' + node()->ordinal());
    char remote_interface_name[32];
    construct_remote_interface_name( this, remote_interface_name,
                                     sizeof(remote_interface_name) );
    log_notice( "Topology change: node%c:%s seen on %s",
                        node_ordinal, remote_interface_name, interface->name() );

    _spine_notified = true;
    monitor->topology_changed();
}

/* vim: set autoindent expandtab sw=4 : */
<commit_msg>fix compile errors<commit_after>
/*
 * Copyright (c) 2012 Karl N. Redgate
 *
 * 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.
 */

/** \file Neighbor.cc
 * \brief
 *
 */

#include <stdint.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <glob.h>
#include <errno.h>

#include <tcl.h>
#include "tcl_util.h"

#include "logger.h"
#include "util.h"
#include "Neighbor.h"
#include "NodeIterator.h"
#include "Interface.h"

/*
 * I do not like this - try to eliminate OS defines
 */
#if defined(__APPLE__) || defined(__darwin__)
/* OSX seems not to define these. */
#ifndef s6_addr16
#define s6_addr16 __u6_addr.__u6_addr16
#endif
#ifndef s6_addr32
#define s6_addr32 __u6_addr.__u6_addr32
#endif
#endif

namespace { int debug = 0; }

/**
 */
void
Network::Node::uuid( UUID& that ) {
    _uuid = that;
    _ordinal = 255;
    valid = true;
    // log_notice( "new node allocated with uuid %s", _uuid.to_s() );
}

/**
 */
void
Network::Node::ordinal( uint8_t value ) {
    _ordinal = value;
    // log_notice( "node%d %s", _ordinal, _uuid.to_s() );
}

/**
 */
bool
Network::Node::operator == ( UUID& that ) {
    return _uuid == that;
}

/**
 */
bool
Network::Node::operator != ( UUID& that ) {
    return _uuid != that;
}

/**
 * Used to iterate through the node list and clear the partner
 * bit in all entries.
 */
class ClearNodePartner : public Network::NodeIterator {
public:
    ClearNodePartner() {}
    virtual ~ClearNodePartner() {}
    virtual int operator() ( Network::Node& node ) {
        if ( node.not_partner() ) return 0;
        log_notice( "clear partner [%s]", node.uuid().to_s() );
        node.clear_partner();
        return 1;
    }
};

/**
 */
Network::Peer::~Peer() {
    if ( _name != NULL ) free( _name );
    _name = NULL;
}

/**
 * This one should be deprecated
 */
Network::Peer::Peer( Network::Node *__node, struct in6_addr *address )
: _node(__node), _ordinal(0), _name(NULL) {
    memcpy( &lladdr, address, sizeof lladdr );
    memset( &neighbor_updated, 0, sizeof neighbor_updated );
}

/**
 */
void
Network::Peer::node( Node *that ) {
    _node = that;

    /*
     * Here we have just discovered a new partner.  If this was the
     * cached partner, then the _node would already be a partner.
     * Since it was not and the neighbor is a partner - it must
     * have been discovered on priv0, which either overrides the
     * cached partner (node replace or the like) or this is the
     * first time we have discovered the partner.  Either way
     * we need to cache the newly discovered partner.
     */
    if ( is_partner() and _node->not_partner() ) {
        _node->make_partner();
        log_notice( "node %s is partner", _node->uuid().to_s() );
    }

    /*
     * Cases that are ignored:
     * peer->not_partner() and _node->not_partner()
     *   -- who cares about this neighbor
     *
     * peer->is_partner() and _node->is_partner()
     *   -- we already have all necessary state
     *
     */

    if ( debug < 2 ) return;
    char buffer[80];
    const char *address_string = inet_ntop(AF_INET6, &lladdr, buffer, sizeof buffer);
    log_notice( "%s at %s is node %s",
                        (_node->is_partner() ? "partner" : "neighbor"),
                        address_string, _node->uuid().to_s() );
}

/**
 */
Network::Node *
Network::Peer::node() const {
    return _node;
}

/**
 * Since this is a sort of allocation method, maybe this should check if
 * already valid and either disallow usage -- or at least report that the
 * address is changing.
 */
void
Network::Peer::address( struct in6_addr *addr ) {
    memcpy( &lladdr, addr, sizeof lladdr );
    valid = true;
    if ( debug < 2 ) return;
    char buffer[80];
    const char *address_string = inet_ntop(AF_INET6, addr, buffer, sizeof buffer);
    log_notice( "new neighbor %s", address_string );
}

/**
 */
void
Network::Peer::set_interface( bool set_private, uint8_t set_ordinal ) {
    _is_private = set_private;
    _ordinal = set_ordinal;
}

/**
 */
void
Network::Peer::set_interface_name( char *name ) {
    if ( name == NULL ) {			// If the new name is NULL...
       if ( _name != NULL ) {			// ...and the Peer had a name...
           free( _name );			//    ...free the old name...
           _name = NULL;			//    ...and invalidate the name.
       }
       return;
    }

    if ( _name != NULL ) {			// If the Peer already has a name...
        if ( strcmp( name, _name ) ) {		// ...and it is *not* the same name...
            free( _name );			//    ...free the old name...
            _name = strdup( name );		//    ...and copy the new name.
        }					// If it *is* the same name, don't do free()/strdup()
    } else {					// If the Peer does not have a name...
        _name = strdup( name );			// ...copy the new name.
    }
}

/**
 */
void
Network::Peer::copy_address( struct in6_addr *address ) const {
    memcpy( address, &lladdr, sizeof lladdr );
}

/**
 */
void
Network::Peer::touch_advertised() {
    gettimeofday( &neighbor_advertised, 0 );
}

/**
 */
void
Network::Peer::touch() {
    gettimeofday( &neighbor_updated, 0 );
}

/**
 */
int
Network::Peer::seconds_since_last_update() const {
    struct timeval now;
    gettimeofday( &now, 0 );
    return now.tv_sec - neighbor_updated.tv_sec;
}

/**
 */
bool
Network::Peer::operator == ( struct in6_addr& that ) {
    if ( that.s6_addr32[0] != lladdr.s6_addr32[0] ) return false;
    if ( that.s6_addr32[1] != lladdr.s6_addr32[1] ) return false;
    if ( that.s6_addr32[2] != lladdr.s6_addr32[2] ) return false;
    if ( that.s6_addr32[3] != lladdr.s6_addr32[3] ) return false;
    return true;
}

/**
 */
bool
Network::Peer::operator != ( struct in6_addr& that ) {
    if ( that.s6_addr32[0] != lladdr.s6_addr32[0] ) return true;
    if ( that.s6_addr32[1] != lladdr.s6_addr32[1] ) return true;
    if ( that.s6_addr32[2] != lladdr.s6_addr32[2] ) return true;
    if ( that.s6_addr32[3] != lladdr.s6_addr32[3] ) return true;
    return false;
}

/**
 */
bool
Network::Peer::has_address( struct in6_addr *address ) {
    if ( address->s6_addr32[0] != lladdr.s6_addr32[0] ) return false;
    if ( address->s6_addr32[1] != lladdr.s6_addr32[1] ) return false;
    if ( address->s6_addr32[2] != lladdr.s6_addr32[2] ) return false;
    if ( address->s6_addr32[3] != lladdr.s6_addr32[3] ) return false;
    return true;
}

/**
 */
static void
construct_remote_interface_name( Network::Peer *neighbor, char *name, int size ) {

    if ( neighbor->name() != NULL ) {
        strncpy( name, neighbor->name(), size );
    } else {
        int ordinal = neighbor->ordinal();
        if ( neighbor->is_private() ) {
            if ( ordinal & 0x40 ) {
                int slot = ( ordinal & 0x3c ) >> 2;
                int port = ( ordinal & 0x03);
                snprintf( name, size, "sync_pci%dp%d", slot, port );
            } else {
                snprintf( name, size, "priv%d", ordinal );
            }
        } else {
            snprintf( name, size, "ibiz%d", ordinal );
        }
    }
}

/**
 */
void
Network::Peer::topology_changed( Network::Monitor *monitor, Network::Interface *interface ) {
    char node_ordinal = (node() == NULL) ? '?' : ('0' + node()->ordinal());
    char remote_interface_name[32];
    construct_remote_interface_name( this, remote_interface_name,
                                     sizeof(remote_interface_name) );
    log_notice( "Topology change: node%c:%s seen on %s",
                        node_ordinal, remote_interface_name, interface->name() );

    _spine_notified = true;
}

/* vim: set autoindent expandtab sw=4 : */
<|endoftext|>


<commit_before>#include "main.h"

void mainLoop()
{
  handleInput();

  glfwGetFramebufferSize(window, &width, &height);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // bottom-left: Euler Camera (float)
  drawQuarter(0, 0, width/2, height/2, rcamf);
  // bottom-right: Euler Camera (double)
  drawQuarter(width/2, 0, width/2, height/2, rcamd);

  // top-left: Quaternion Camera (float)
  drawQuarter(0, height/2, width/2, height/2, qcamf);
  // top-right: Quaternion Camera (double)
  drawQuarter(width/2, height/2, width/2, height/2, qcamd);

  double rdiff = getDifference(rcamf, rcamd);
  double qdiff = getDifference(qcamf, qcamd);

  cout.precision(15);
  cout << std::fixed << rdiff << ", " << qdiff << endl;

  /* Swap front and back buffers */
  glfwSwapBuffers(window);
  /* Poll for and process events */
  glfwPollEvents();
}

void handleInput()
{
  if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
  {
    glfwSetWindowShouldClose(window, GL_TRUE);
  }

  double x, y;
  int key;
  if (is_reading)
  {
    if (!(input_file >> mouse_ready))
    {
      glfwSetWindowShouldClose(window, GL_TRUE);
      return;
    }
    input_file >> x >> y;

    input_file >> key;
    while (key != -1)
    {
      doKeyToCameras(key);
      input_file >> key;
    }
  }
  else
  {
    glfwGetCursorPos(window, &x, &y);

    if (is_writing)
      output_file << mouse_ready << " " << x << " " << y << " ";

    for (unsigned i = 0; i < sizeof(KEYS)/sizeof(int); i++)
    {
      if (glfwGetKey(window, KEYS[i]) == GLFW_PRESS)
      {
        doKeyToCameras(KEYS[i]);

        if (is_writing)
          output_file << KEYS[i] << " ";
      }
    }

    if (is_writing)
      output_file << "-1" << endl;
  }
  mouseMoved(x, y);
}

void doKeyToCameras(int key)
{
  rcamf->doKey(key);
  rcamd->doKey(key);
  qcamf->doKey(key);
  qcamd->doKey(key);
}

void mouseCheck(GLFWwindow*,double x,double y)
{
  if (!mouse_ready)
  {
    mouse_ready = true;
    mx = x; my = y;

    if (is_writing)
      output_file << "0 " << mx << " " << my << " -1 ";
  }
}

void mouseMoved(double x, double y)
{
  if (mouse_ready)
  {
    double dx = x - mx;
    double dy = y - my;

    rcamf->mouseLook((float)dx,(float)dy);
    qcamf->mouseLook((float)dx,(float)dy);

    rcamd->mouseLook(dx,dy);
    qcamd->mouseLook(dx,dy);
  }

  mx = x; my = y;
}

void initGlfw()
{
  if (!glfwInit())
      exit(-1);

// Because Apple refuses to keep up with standards!
#ifdef __APPLE__
  glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 2);
  glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
}

void init()
{
  initGlfw();
  initWindow();
  initGlew();

  glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

  if (!is_reading)
    glfwSetCursorPosCallback(window, mouseCheck);

  glEnable(GL_VERTEX_ARRAY);
  glEnable(GL_DEPTH_TEST);
  glDisable(GL_CULL_FACE);

  glClearColor(1,1,1,1);
}

void initWindow()
{
  window = glfwCreateWindow(640, 480, "Euler vs Hamilton", NULL, NULL);
  if (!window)
  {
      glfwTerminate();
      exit(-1);
  }

  /* Make the window's context current */
  glfwMakeContextCurrent(window);
}

void initGlew()
{
  glewExperimental = GL_TRUE;
  glewInit();
}

void loadShaders()
{
  shader_program = glCreateProgram();

  GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
  glShaderSource(vertex_shader, 1, &vertex_glsl, NULL);
  glCompileShader(vertex_shader);
  shaderLog(vertex_shader);

  GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
  glShaderSource(fragment_shader, 1, &fragment_glsl, NULL);
  glCompileShader(fragment_shader);
  shaderLog(fragment_shader);

  glAttachShader(shader_program, vertex_shader);
  glAttachShader(shader_program, fragment_shader);

  glLinkProgram(shader_program);
  programLog(shader_program);

  glUseProgram(shader_program);

  view_location = glGetUniformLocation(shader_program, "view");
  projection_location = glGetUniformLocation(shader_program, "projection");
  world_location = glGetUniformLocation(shader_program, "world");
}

void loadGeometry()
{
  int i = 0;
  verts[i++] = -1.0f;
  verts[i++] = 0.0f;
  verts[i++] = -1.0f;

  verts[i++] = 1.0f;
  verts[i++] = 0.0f;
  verts[i++] = -1.0f;

  verts[i++] = 1.0f;
  verts[i++] = 0.0f;
  verts[i++] = 1.0f;

  verts[i++] = -1.0f;
  verts[i++] = 0.0f;
  verts[i++] = 1.0f;

  i = 0;
  faces[i++] = 0;
  faces[i++] = 2;
  faces[i++] = 1;

  faces[i++] = 0;
  faces[i++] = 3;
  faces[i++] = 2;

  GLuint vptr, iptr;

  glGenVertexArrays(1, &quad);
  glBindVertexArray(quad);

  glGenBuffers(1, &vptr);
  glBindBuffer(GL_ARRAY_BUFFER, vptr);

  glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(VERTEX_ARRAY_SIZE *
    sizeof(GLfloat)), verts, GL_STATIC_DRAW);

  glGenBuffers(1, &iptr);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iptr);

  glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(INDEX_ARRAY_SIZE *
    sizeof(GLuint)), faces, GL_STATIC_DRAW);

  glEnableVertexAttribArray(POSITION_LOC);
  glVertexAttribPointer(POSITION_LOC, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
          (GLsizei)(VERTEX_SIZE * sizeof(GLfloat)), 0);

  world = scale(world, vec3(10,10,10));

  glUniformMatrix4fv(world_location, 1, GL_FALSE, value_ptr(world));
}

double getDifference(CamF* camf, CamD* camd)
{
  CamD::mat4_type matf = (CamD::mat4_type) camf->getMat();
  CamD::mat4_type matd = camd->getMat();

  double diff = 0;

  for (int i = 0; i < 4; i++)
  {
    tvec4<double,highp> v = column(matf, i) - column(matd, i);

    diff += (v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w);
  }

  return diff/16.0;
}

void handleArguments(int argc, char ** argv)
{
  for (int i = 1; i < argc; i++)
  {
    if (strcmp(argv[i], "-i") == 0)
    {
      i++;
      input_file.open(argv[i]);
      is_reading = true;
    }
    else if (strcmp(argv[i], "-o") == 0)
    {
      i++;
      output_file.open(argv[i]);
      is_writing = true;
    }
  }
}

int main(int argc, char ** argv)
{
  handleArguments(argc, argv);

  init();

  loadShaders();

  loadGeometry();

  cout << ("Euler, Quaternion") << endl;

  /* Loop until the user closes the window */
  while (!glfwWindowShouldClose(window))
  {
    mainLoop();
  }

  glfwTerminate();

  input_file.close();
  output_file.close();

  return 0;
}
<commit_msg>Don't disable cursor if we are reading from file<commit_after>#include "main.h"

void mainLoop()
{
  handleInput();

  glfwGetFramebufferSize(window, &width, &height);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // bottom-left: Euler Camera (float)
  drawQuarter(0, 0, width/2, height/2, rcamf);
  // bottom-right: Euler Camera (double)
  drawQuarter(width/2, 0, width/2, height/2, rcamd);

  // top-left: Quaternion Camera (float)
  drawQuarter(0, height/2, width/2, height/2, qcamf);
  // top-right: Quaternion Camera (double)
  drawQuarter(width/2, height/2, width/2, height/2, qcamd);

  double rdiff = getDifference(rcamf, rcamd);
  double qdiff = getDifference(qcamf, qcamd);

  cout.precision(15);
  cout << std::fixed << rdiff << ", " << qdiff << endl;

  /* Swap front and back buffers */
  glfwSwapBuffers(window);
  /* Poll for and process events */
  glfwPollEvents();
}

void handleInput()
{
  if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
  {
    glfwSetWindowShouldClose(window, GL_TRUE);
  }

  double x, y;
  int key;
  if (is_reading)
  {
    if (!(input_file >> mouse_ready))
    {
      glfwSetWindowShouldClose(window, GL_TRUE);
      return;
    }
    input_file >> x >> y;

    input_file >> key;
    while (key != -1)
    {
      doKeyToCameras(key);
      input_file >> key;
    }
  }
  else
  {
    glfwGetCursorPos(window, &x, &y);

    if (is_writing)
      output_file << mouse_ready << " " << x << " " << y << " ";

    for (unsigned i = 0; i < sizeof(KEYS)/sizeof(int); i++)
    {
      if (glfwGetKey(window, KEYS[i]) == GLFW_PRESS)
      {
        doKeyToCameras(KEYS[i]);

        if (is_writing)
          output_file << KEYS[i] << " ";
      }
    }

    if (is_writing)
      output_file << "-1" << endl;
  }
  mouseMoved(x, y);
}

void doKeyToCameras(int key)
{
  rcamf->doKey(key);
  rcamd->doKey(key);
  qcamf->doKey(key);
  qcamd->doKey(key);
}

void mouseCheck(GLFWwindow*,double x,double y)
{
  if (!mouse_ready)
  {
    mouse_ready = true;
    mx = x; my = y;

    if (is_writing)
      output_file << "0 " << mx << " " << my << " -1 ";
  }
}

void mouseMoved(double x, double y)
{
  if (mouse_ready)
  {
    double dx = x - mx;
    double dy = y - my;

    rcamf->mouseLook((float)dx,(float)dy);
    qcamf->mouseLook((float)dx,(float)dy);

    rcamd->mouseLook(dx,dy);
    qcamd->mouseLook(dx,dy);
  }

  mx = x; my = y;
}

void initGlfw()
{
  if (!glfwInit())
      exit(-1);

// Because Apple refuses to keep up with standards!
#ifdef __APPLE__
  glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 2);
  glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
}

void init()
{
  initGlfw();
  initWindow();
  initGlew();

  if (!is_reading)
  {
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
    glfwSetCursorPosCallback(window, mouseCheck);
  }

  glEnable(GL_VERTEX_ARRAY);
  glEnable(GL_DEPTH_TEST);
  glDisable(GL_CULL_FACE);

  glClearColor(1,1,1,1);
}

void initWindow()
{
  window = glfwCreateWindow(640, 480, "Euler vs Hamilton", NULL, NULL);
  if (!window)
  {
      glfwTerminate();
      exit(-1);
  }

  /* Make the window's context current */
  glfwMakeContextCurrent(window);
}

void initGlew()
{
  glewExperimental = GL_TRUE;
  glewInit();
}

void loadShaders()
{
  shader_program = glCreateProgram();

  GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
  glShaderSource(vertex_shader, 1, &vertex_glsl, NULL);
  glCompileShader(vertex_shader);
  shaderLog(vertex_shader);

  GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
  glShaderSource(fragment_shader, 1, &fragment_glsl, NULL);
  glCompileShader(fragment_shader);
  shaderLog(fragment_shader);

  glAttachShader(shader_program, vertex_shader);
  glAttachShader(shader_program, fragment_shader);

  glLinkProgram(shader_program);
  programLog(shader_program);

  glUseProgram(shader_program);

  view_location = glGetUniformLocation(shader_program, "view");
  projection_location = glGetUniformLocation(shader_program, "projection");
  world_location = glGetUniformLocation(shader_program, "world");
}

void loadGeometry()
{
  int i = 0;
  verts[i++] = -1.0f;
  verts[i++] = 0.0f;
  verts[i++] = -1.0f;

  verts[i++] = 1.0f;
  verts[i++] = 0.0f;
  verts[i++] = -1.0f;

  verts[i++] = 1.0f;
  verts[i++] = 0.0f;
  verts[i++] = 1.0f;

  verts[i++] = -1.0f;
  verts[i++] = 0.0f;
  verts[i++] = 1.0f;

  i = 0;
  faces[i++] = 0;
  faces[i++] = 2;
  faces[i++] = 1;

  faces[i++] = 0;
  faces[i++] = 3;
  faces[i++] = 2;

  GLuint vptr, iptr;

  glGenVertexArrays(1, &quad);
  glBindVertexArray(quad);

  glGenBuffers(1, &vptr);
  glBindBuffer(GL_ARRAY_BUFFER, vptr);

  glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(VERTEX_ARRAY_SIZE *
    sizeof(GLfloat)), verts, GL_STATIC_DRAW);

  glGenBuffers(1, &iptr);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iptr);

  glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(INDEX_ARRAY_SIZE *
    sizeof(GLuint)), faces, GL_STATIC_DRAW);

  glEnableVertexAttribArray(POSITION_LOC);
  glVertexAttribPointer(POSITION_LOC, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
          (GLsizei)(VERTEX_SIZE * sizeof(GLfloat)), 0);

  world = scale(world, vec3(10,10,10));

  glUniformMatrix4fv(world_location, 1, GL_FALSE, value_ptr(world));
}

double getDifference(CamF* camf, CamD* camd)
{
  CamD::mat4_type matf = (CamD::mat4_type) camf->getMat();
  CamD::mat4_type matd = camd->getMat();

  double diff = 0;

  for (int i = 0; i < 4; i++)
  {
    tvec4<double,highp> v = column(matf, i) - column(matd, i);

    diff += (v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w);
  }

  return diff/16.0;
}

void handleArguments(int argc, char ** argv)
{
  for (int i = 1; i < argc; i++)
  {
    if (strcmp(argv[i], "-i") == 0)
    {
      i++;
      input_file.open(argv[i]);
      is_reading = true;
    }
    else if (strcmp(argv[i], "-o") == 0)
    {
      i++;
      output_file.open(argv[i]);
      is_writing = true;
    }
  }
}

int main(int argc, char ** argv)
{
  handleArguments(argc, argv);

  init();

  loadShaders();

  loadGeometry();

  cout << ("Euler, Quaternion") << endl;

  /* Loop until the user closes the window */
  while (!glfwWindowShouldClose(window))
  {
    mainLoop();
  }

  glfwTerminate();

  input_file.close();
  output_file.close();

  return 0;
}
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
 * @author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#ifndef NDN_SIGNED_BLOB_HPP
#define	NDN_SIGNED_BLOB_HPP

#include "blob.hpp"

namespace ndn {

/**
 * A SignedBlob extends Blob to keep the offsets of a signed portion (e.g., the bytes of Data packet).
 */
class SignedBlob : public Blob {
public:
  /**
   * Create a new SignedBlob with an immutable copy of the given array.
   * @param value A pointer to the byte array which is copied.
   * @param valueLength The length of value.
   * @param signedPortionBeginOffset The offset in the encoding of the beginning of the signed portion.
   * @param signedPortionEndOffset The offset in the encoding of the end of the signed portion.
   */
  SignedBlob
    (const unsigned char* value, unsigned int valueLength, unsigned int signedPortionBeginOffset, unsigned int signedPortionEndOffset)
  : Blob(value, valueLength), signedPortionBeginOffset_(signedPortionBeginOffset), signedPortionEndOffset_(signedPortionEndOffset)
  {
  }

  /**
   * Create a new SignedBlob with an immutable copy of the array in the given vector.
   * If you want to transfer the array without copying, the the vector has to start as a
   * ptr_lib::shared_ptr<std::vector<unsigned char> > and you can use the SignedBlob constructor with this type.
   * @param value A reference to a vector which is copied.
   * @param signedPortionBeginOffset The offset in the encoding of the beginning of the signed portion.
   * @param signedPortionEndOffset The offset in the encoding of the end of the signed portion.
   */
  SignedBlob
    (const std::vector<unsigned char> &value, unsigned int signedPortionBeginOffset, unsigned int signedPortionEndOffset)
  : Blob(value), signedPortionBeginOffset_(signedPortionBeginOffset), signedPortionEndOffset_(signedPortionEndOffset)
  {
  }

  /**
   * Create a new SignedBlob to point to an existing byte array.  IMPORTANT: After calling this constructor,
   * if you keep a pointer to the array then you must treat the array as immutable and promise not to change it.
   * @param value A pointer to a vector with the byte array.  This takes another reference and does not copy the bytes.
   * @param signedPortionBeginOffset The offset in the array of the beginning of the signed portion.
   * @param signedPortionEndOffset The offset in the array of the end of the signed portion.
   */
  SignedBlob
    (const ptr_lib::shared_ptr<std::vector<unsigned char> > &value,
     unsigned int signedPortionBeginOffset, unsigned int signedPortionEndOffset)
  : Blob(value), signedPortionBeginOffset_(signedPortionBeginOffset), signedPortionEndOffset_(signedPortionEndOffset)
  {
  }
  SignedBlob
    (const ptr_lib::shared_ptr<const std::vector<unsigned char> > &value,
     unsigned int signedPortionBeginOffset, unsigned int signedPortionEndOffset)
  : Blob(value), signedPortionBeginOffset_(signedPortionBeginOffset), signedPortionEndOffset_(signedPortionEndOffset)
  {
  }

  /**
   * Return the length of the signed portion of the immutable byte array, or 0 of the pointer to the array is null.
   */
  unsigned int signedSize() const
  {
    if (*this)
      return signedPortionEndOffset_ - signedPortionBeginOffset_;
    else
      return 0;
  }

  /**
   * Return a const pointer to the first byte of the signed portion of the immutable byte array, or 0 if the
   * pointer to the array is null.
   */
  const unsigned char* signedBuf() const
  {
    if (*this)
      return &(*this)->front() + signedPortionBeginOffset_;
    else
      return 0;
  }

  /**
   * Return the offset in the array of the beginning of the signed portion.
   */
  unsigned int getSignedPortionBeginOffset() { return signedPortionBeginOffset_; }

  /**
   * Return the offset in the array of the end of the signed portion.
   */
  unsigned int getSignedPortionEndOffset() { return signedPortionEndOffset_; }

private:
  unsigned int signedPortionBeginOffset_;
  unsigned int signedPortionEndOffset_;
};

}

#endif
<commit_msg>Added a default constructor.<commit_after>/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
 * @author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#ifndef NDN_SIGNED_BLOB_HPP
#define	NDN_SIGNED_BLOB_HPP

#include "blob.hpp"

namespace ndn {

/**
 * A SignedBlob extends Blob to keep the offsets of a signed portion (e.g., the bytes of Data packet).
 */
class SignedBlob : public Blob {
public:
  /**
   * Create a new SignedBlob with a null pointer.
   */
  SignedBlob()
  : signedPortionBeginOffset_(0), signedPortionEndOffset_(0)
  {
  }

  /**
   * Create a new SignedBlob with an immutable copy of the given array.
   * @param value A pointer to the byte array which is copied.
   * @param valueLength The length of value.
   * @param signedPortionBeginOffset The offset in the encoding of the beginning of the signed portion.
   * @param signedPortionEndOffset The offset in the encoding of the end of the signed portion.
   */
  SignedBlob
    (const unsigned char* value, unsigned int valueLength, unsigned int signedPortionBeginOffset, unsigned int signedPortionEndOffset)
  : Blob(value, valueLength), signedPortionBeginOffset_(signedPortionBeginOffset), signedPortionEndOffset_(signedPortionEndOffset)
  {
  }

  /**
   * Create a new SignedBlob with an immutable copy of the array in the given vector.
   * If you want to transfer the array without copying, the the vector has to start as a
   * ptr_lib::shared_ptr<std::vector<unsigned char> > and you can use the SignedBlob constructor with this type.
   * @param value A reference to a vector which is copied.
   * @param signedPortionBeginOffset The offset in the encoding of the beginning of the signed portion.
   * @param signedPortionEndOffset The offset in the encoding of the end of the signed portion.
   */
  SignedBlob
    (const std::vector<unsigned char> &value, unsigned int signedPortionBeginOffset, unsigned int signedPortionEndOffset)
  : Blob(value), signedPortionBeginOffset_(signedPortionBeginOffset), signedPortionEndOffset_(signedPortionEndOffset)
  {
  }

  /**
   * Create a new SignedBlob to point to an existing byte array.  IMPORTANT: After calling this constructor,
   * if you keep a pointer to the array then you must treat the array as immutable and promise not to change it.
   * @param value A pointer to a vector with the byte array.  This takes another reference and does not copy the bytes.
   * @param signedPortionBeginOffset The offset in the array of the beginning of the signed portion.
   * @param signedPortionEndOffset The offset in the array of the end of the signed portion.
   */
  SignedBlob
    (const ptr_lib::shared_ptr<std::vector<unsigned char> > &value,
     unsigned int signedPortionBeginOffset, unsigned int signedPortionEndOffset)
  : Blob(value), signedPortionBeginOffset_(signedPortionBeginOffset), signedPortionEndOffset_(signedPortionEndOffset)
  {
  }
  SignedBlob
    (const ptr_lib::shared_ptr<const std::vector<unsigned char> > &value,
     unsigned int signedPortionBeginOffset, unsigned int signedPortionEndOffset)
  : Blob(value), signedPortionBeginOffset_(signedPortionBeginOffset), signedPortionEndOffset_(signedPortionEndOffset)
  {
  }

  /**
   * Return the length of the signed portion of the immutable byte array, or 0 of the pointer to the array is null.
   */
  unsigned int signedSize() const
  {
    if (*this)
      return signedPortionEndOffset_ - signedPortionBeginOffset_;
    else
      return 0;
  }

  /**
   * Return a const pointer to the first byte of the signed portion of the immutable byte array, or 0 if the
   * pointer to the array is null.
   */
  const unsigned char* signedBuf() const
  {
    if (*this)
      return &(*this)->front() + signedPortionBeginOffset_;
    else
      return 0;
  }

  /**
   * Return the offset in the array of the beginning of the signed portion.
   */
  unsigned int getSignedPortionBeginOffset() { return signedPortionBeginOffset_; }

  /**
   * Return the offset in the array of the end of the signed portion.
   */
  unsigned int getSignedPortionEndOffset() { return signedPortionEndOffset_; }

private:
  unsigned int signedPortionBeginOffset_;
  unsigned int signedPortionEndOffset_;
};

}

#endif
<|endoftext|>


<commit_before><commit_msg>Disk Cache: Make sure that file descriptors are valid before calling close().<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2019 pengjian.uestc @ gmail.com
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "redis/server.hh"
#include "service/storage_service.hh"
#include "db/consistency_level_type.hh"
#include "db/config.hh"
#include "db/write_type.hh"
#include <seastar/core/future-util.hh>
#include <seastar/core/seastar.hh>
#include <seastar/net/byteorder.hh>
#include <seastar/core/execution_stage.hh>
#include "service/query_state.hh"
#include "exceptions/exceptions.hh"
#include "auth/authenticator.hh"
#include <cassert>
#include <string>
#include "redis/request.hh"
#include "redis/reply.hh"
#include <unordered_map>

namespace redis_transport {

static logging::logger logging("redis_server");

redis_server::redis_server(distributed<service::storage_proxy>& proxy, distributed<redis::query_processor>& qp, auth::service& auth_service, redis_server_config config)
    : _proxy(proxy)
    , _query_processor(qp)
    , _config(config)
    , _max_request_size(config._max_request_size)
    , _memory_available(_max_request_size)
    , _auth_service(auth_service)
    , _total_redis_db_count(config._total_redis_db_count)
{
}

future<> redis_server::stop() {
    _stopping = true;
    size_t nr = 0;
    size_t nr_total = _listeners.size();
    logging.debug("redis_server: abort accept nr_total={}", nr_total);
    for (auto&& l : _listeners) {
        l.abort_accept();
        logging.debug("redis_server: abort accept {} out of {} done", ++nr, nr_total);
    }
    auto nr_conn = make_lw_shared<size_t>(0);
    auto nr_conn_total = _connections_list.size();
    logging.debug("redis_server: shutdown connection nr_total={}", nr_conn_total);
    return parallel_for_each(_connections_list.begin(), _connections_list.end(), [nr_conn, nr_conn_total] (auto&& c) {
        return c.shutdown().then([nr_conn, nr_conn_total] {
            logging.debug("redis_server: shutdown connection {} out of {} done", ++(*nr_conn), nr_conn_total);
        });
    }).then([this] {
        return std::move(_stopped);
    });
}

future<> redis_server::listen(socket_address addr, std::shared_ptr<seastar::tls::credentials_builder> creds, bool keepalive) {
    listen_options lo;
    lo.reuse_address = true;
    server_socket ss;
    try {
        ss = creds
          ? seastar::tls::listen(creds->build_server_credentials(), addr, lo)
          : seastar::listen(addr, lo);
    } catch (...) {
        throw std::runtime_error(sprint("Redis server error while listening on %s -> %s", addr, std::current_exception()));
    }
    _listeners.emplace_back(std::move(ss));
    _stopped = when_all(std::move(_stopped), do_accepts(_listeners.size() - 1, keepalive, addr)).discard_result();
    return make_ready_future<>();
}

future<> redis_server::do_accepts(int which, bool keepalive, socket_address server_addr) {
    return repeat([this, which, keepalive, server_addr] {
        ++_stats._connections_being_accepted;
        return _listeners[which].accept().then_wrapped([this, which, keepalive, server_addr] (future<accept_result> f_cs_sa) mutable {
            --_stats._connections_being_accepted;
            if (_stopping) {
                f_cs_sa.ignore_ready_future();
                maybe_idle();
                return stop_iteration::yes;
            }
            auto cs_sa = f_cs_sa.get0();
            auto fd = std::move(cs_sa.connection);
            auto addr = std::move(cs_sa.remote_address);
            fd.set_nodelay(true);
            fd.set_keepalive(keepalive);
            auto conn = make_shared<connection>(*this, server_addr, std::move(fd), std::move(addr));
            ++_stats._connects;
            ++_stats._connections;
            (void)conn->process().then_wrapped([this, conn] (future<> f) {
                --_stats._connections;
                try {
                    f.get();
                } catch (...) {
                    logging.debug("connection error: {}", std::current_exception());
                }
            });
            return stop_iteration::no;
        }).handle_exception([] (auto ep) {
            logging.debug("accept failed: {}", ep);
            return stop_iteration::no;
        });
    });
}

future<redis_server::result> redis_server::connection::process_request_one(redis::request&& request, redis::redis_options& opts, service_permit permit) {
    return futurize_invoke([this, request = std::move(request), &opts, permit] () mutable {
        return _server._query_processor.local().process(std::move(request), seastar::ref(opts), permit).then([] (auto&& message) {
            return make_ready_future<redis_server::result> (std::move(message));
        });
    });
}

redis_server::connection::connection(redis_server& server, socket_address server_addr, connected_socket&& fd, socket_address addr)
    : _server(server)
    , _server_addr(server_addr)
    , _fd(std::move(fd))
    , _read_buf(_fd.input())
    , _write_buf(_fd.output())
    , _options(server._config._read_consistency_level, server._config._write_consistency_level, server._config._timeout_config, server._auth_service, addr, server._total_redis_db_count)
{
    ++_server._stats._total_connections;
    ++_server._stats._current_connections;
    _server._connections_list.push_back(*this);
}

redis_server::connection::~connection() {
    --_server._stats._current_connections;
    _server._connections_list.erase(_server._connections_list.iterator_to(*this));
    _server.maybe_idle();
}

future<> redis_server::connection::process()
{
    return do_until([this] {
        return _read_buf.eof();
    }, [this] {
        return with_gate(_pending_requests_gate, [this] {
            return process_request().then_wrapped([this] (auto f) {
                try {
                    f.get();
                }
                catch (redis_exception& e) {
                    write_reply(e);
                }
                catch (std::exception& e) {
                    write_reply(redis_exception { e.what() });
                }
                catch (...) {
                    write_reply(redis_exception { "Unknown exception" });
                }
            });
        });
    }).finally([this] {
        return _pending_requests_gate.close().then([this] {
            return _ready_to_respond.finally([this] {
                return _write_buf.close();
            });
        });
    });
}

future<> redis_server::connection::shutdown()
{
    try {
        _fd.shutdown_input();
        _fd.shutdown_output();
    } catch (...) {
    }
    return make_ready_future<>();
}

thread_local redis_server::connection::execution_stage_type redis_server::connection::_process_request_stage {"redis_transport", &connection::process_request_one};

future<redis_server::result> redis_server::connection::process_request_internal() {
    return _process_request_stage(this, std::move(_parser.get_request()), seastar::ref(_options), empty_service_permit());
}

void redis_server::connection::write_reply(const redis_exception& e)
{
    _ready_to_respond = _ready_to_respond.then([this, exception_message = e.what_message()] () mutable {
        return redis_message::exception(exception_message).then([this] (auto&& result) {
            auto m = result.message();
            return _write_buf.write(std::move(*m)).then([this] {
                return _write_buf.flush();
            });
        });
    });
}

void redis_server::connection::write_reply(redis_server::result result)
{
    _ready_to_respond = _ready_to_respond.then([this, result = std::move(result)] () mutable {
        auto m = result.make_message();
        return _write_buf.write(std::move(*m)).then([this] {
            return _write_buf.flush();
        });
    });
}
future<> redis_server::connection::process_request() {
    _parser.init();
    return _read_buf.consume(_parser).then([this] {
        if (_parser.eof()) {
            return make_ready_future<>();
        }
        ++_server._stats._requests_serving;
        _pending_requests_gate.enter();
        utils::latency_counter lc;
        lc.start();
        auto leave = defer([this] { _pending_requests_gate.leave(); });
        return process_request_internal().then([this, leave = std::move(leave), lc = std::move(lc)] (auto&& result) mutable {
            --_server._stats._requests_serving;
            try {
                write_reply(std::move(result));
                ++_server._stats._requests_served;
                _server._stats._requests.mark(lc.stop().latency());
                if (lc.is_start()) {
                    _server._stats._estimated_requests_latency.add(lc.latency(), _server._stats._requests.hist.count);
                }
            } catch (...) {
                logging.error("request processing failed: {}", std::current_exception());
            }
        });
    });
}

static inline bytes_view to_bytes_view(temporary_buffer<char>& b)
{
    using byte = bytes_view::value_type;
    return bytes_view(reinterpret_cast<const byte*>(b.get()), b.size());
}

}

db::consistency_level make_consistency_level(const sstring& level)
{
    std::unordered_map<sstring, db::consistency_level> consistency_levels {
        {"ONE", db::consistency_level::ONE},
        {"QUORUM", db::consistency_level::QUORUM},
        {"LOCAL_QUORUM", db::consistency_level::LOCAL_QUORUM},
        {"EACH_QUORUM", db::consistency_level::EACH_QUORUM},
        {"ALL", db::consistency_level::ALL},
        {"ANY", db::consistency_level::ANY},
        {"TWO", db::consistency_level::TWO},
        {"THREE", db::consistency_level::THREE},
        {"SERIAL", db::consistency_level::SERIAL},
        {"LOCAL_SERIAL", db::consistency_level::LOCAL_SERIAL},
        {"LOCAL_ONE", db::consistency_level::LOCAL_ONE},
    };
    auto iter_cl = consistency_levels.find(level);
    if (iter_cl == consistency_levels.end()) {
        return db::consistency_level::ONE;
    }
    return iter_cl->second;
}
<commit_msg>redis: Use reloadable tls certificates<commit_after>/*
 * Copyright (C) 2019 pengjian.uestc @ gmail.com
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "redis/server.hh"
#include "service/storage_service.hh"
#include "db/consistency_level_type.hh"
#include "db/config.hh"
#include "db/write_type.hh"
#include <seastar/core/future-util.hh>
#include <seastar/core/seastar.hh>
#include <seastar/net/byteorder.hh>
#include <seastar/core/execution_stage.hh>
#include "service/query_state.hh"
#include "exceptions/exceptions.hh"
#include "auth/authenticator.hh"
#include <cassert>
#include <string>
#include "redis/request.hh"
#include "redis/reply.hh"
#include <unordered_map>

namespace redis_transport {

static logging::logger logging("redis_server");

redis_server::redis_server(distributed<service::storage_proxy>& proxy, distributed<redis::query_processor>& qp, auth::service& auth_service, redis_server_config config)
    : _proxy(proxy)
    , _query_processor(qp)
    , _config(config)
    , _max_request_size(config._max_request_size)
    , _memory_available(_max_request_size)
    , _auth_service(auth_service)
    , _total_redis_db_count(config._total_redis_db_count)
{
}

future<> redis_server::stop() {
    _stopping = true;
    size_t nr = 0;
    size_t nr_total = _listeners.size();
    logging.debug("redis_server: abort accept nr_total={}", nr_total);
    for (auto&& l : _listeners) {
        l.abort_accept();
        logging.debug("redis_server: abort accept {} out of {} done", ++nr, nr_total);
    }
    auto nr_conn = make_lw_shared<size_t>(0);
    auto nr_conn_total = _connections_list.size();
    logging.debug("redis_server: shutdown connection nr_total={}", nr_conn_total);
    return parallel_for_each(_connections_list.begin(), _connections_list.end(), [nr_conn, nr_conn_total] (auto&& c) {
        return c.shutdown().then([nr_conn, nr_conn_total] {
            logging.debug("redis_server: shutdown connection {} out of {} done", ++(*nr_conn), nr_conn_total);
        });
    }).then([this] {
        return std::move(_stopped);
    });
}

future<> redis_server::listen(socket_address addr, std::shared_ptr<seastar::tls::credentials_builder> creds, bool keepalive) {
    auto f = make_ready_future<shared_ptr<seastar::tls::server_credentials>>(nullptr);
    if (creds) {
        f = creds->build_reloadable_server_credentials([](const std::unordered_set<sstring>& files, std::exception_ptr ep) {
            if (ep) {
                logging.warn("Exception loading {}: {}", files, ep);
            } else {
                logging.info("Reloaded {}", files);
            }
        });
    }
    return f.then([this, addr, keepalive](shared_ptr<seastar::tls::server_credentials> creds) {
        listen_options lo;
        lo.reuse_address = true;
        server_socket ss;
        try {
            ss = creds
                ? seastar::tls::listen(std::move(creds), addr, lo)
                : seastar::listen(addr, lo);
        } catch (...) {
            throw std::runtime_error(sprint("Redis server error while listening on %s -> %s", addr, std::current_exception()));
        }
        _listeners.emplace_back(std::move(ss));
        _stopped = when_all(std::move(_stopped), do_accepts(_listeners.size() - 1, keepalive, addr)).discard_result();
    });
}

future<> redis_server::do_accepts(int which, bool keepalive, socket_address server_addr) {
    return repeat([this, which, keepalive, server_addr] {
        ++_stats._connections_being_accepted;
        return _listeners[which].accept().then_wrapped([this, which, keepalive, server_addr] (future<accept_result> f_cs_sa) mutable {
            --_stats._connections_being_accepted;
            if (_stopping) {
                f_cs_sa.ignore_ready_future();
                maybe_idle();
                return stop_iteration::yes;
            }
            auto cs_sa = f_cs_sa.get0();
            auto fd = std::move(cs_sa.connection);
            auto addr = std::move(cs_sa.remote_address);
            fd.set_nodelay(true);
            fd.set_keepalive(keepalive);
            auto conn = make_shared<connection>(*this, server_addr, std::move(fd), std::move(addr));
            ++_stats._connects;
            ++_stats._connections;
            (void)conn->process().then_wrapped([this, conn] (future<> f) {
                --_stats._connections;
                try {
                    f.get();
                } catch (...) {
                    logging.debug("connection error: {}", std::current_exception());
                }
            });
            return stop_iteration::no;
        }).handle_exception([] (auto ep) {
            logging.debug("accept failed: {}", ep);
            return stop_iteration::no;
        });
    });
}

future<redis_server::result> redis_server::connection::process_request_one(redis::request&& request, redis::redis_options& opts, service_permit permit) {
    return futurize_invoke([this, request = std::move(request), &opts, permit] () mutable {
        return _server._query_processor.local().process(std::move(request), seastar::ref(opts), permit).then([] (auto&& message) {
            return make_ready_future<redis_server::result> (std::move(message));
        });
    });
}

redis_server::connection::connection(redis_server& server, socket_address server_addr, connected_socket&& fd, socket_address addr)
    : _server(server)
    , _server_addr(server_addr)
    , _fd(std::move(fd))
    , _read_buf(_fd.input())
    , _write_buf(_fd.output())
    , _options(server._config._read_consistency_level, server._config._write_consistency_level, server._config._timeout_config, server._auth_service, addr, server._total_redis_db_count)
{
    ++_server._stats._total_connections;
    ++_server._stats._current_connections;
    _server._connections_list.push_back(*this);
}

redis_server::connection::~connection() {
    --_server._stats._current_connections;
    _server._connections_list.erase(_server._connections_list.iterator_to(*this));
    _server.maybe_idle();
}

future<> redis_server::connection::process()
{
    return do_until([this] {
        return _read_buf.eof();
    }, [this] {
        return with_gate(_pending_requests_gate, [this] {
            return process_request().then_wrapped([this] (auto f) {
                try {
                    f.get();
                }
                catch (redis_exception& e) {
                    write_reply(e);
                }
                catch (std::exception& e) {
                    write_reply(redis_exception { e.what() });
                }
                catch (...) {
                    write_reply(redis_exception { "Unknown exception" });
                }
            });
        });
    }).finally([this] {
        return _pending_requests_gate.close().then([this] {
            return _ready_to_respond.finally([this] {
                return _write_buf.close();
            });
        });
    });
}

future<> redis_server::connection::shutdown()
{
    try {
        _fd.shutdown_input();
        _fd.shutdown_output();
    } catch (...) {
    }
    return make_ready_future<>();
}

thread_local redis_server::connection::execution_stage_type redis_server::connection::_process_request_stage {"redis_transport", &connection::process_request_one};

future<redis_server::result> redis_server::connection::process_request_internal() {
    return _process_request_stage(this, std::move(_parser.get_request()), seastar::ref(_options), empty_service_permit());
}

void redis_server::connection::write_reply(const redis_exception& e)
{
    _ready_to_respond = _ready_to_respond.then([this, exception_message = e.what_message()] () mutable {
        return redis_message::exception(exception_message).then([this] (auto&& result) {
            auto m = result.message();
            return _write_buf.write(std::move(*m)).then([this] {
                return _write_buf.flush();
            });
        });
    });
}

void redis_server::connection::write_reply(redis_server::result result)
{
    _ready_to_respond = _ready_to_respond.then([this, result = std::move(result)] () mutable {
        auto m = result.make_message();
        return _write_buf.write(std::move(*m)).then([this] {
            return _write_buf.flush();
        });
    });
}
future<> redis_server::connection::process_request() {
    _parser.init();
    return _read_buf.consume(_parser).then([this] {
        if (_parser.eof()) {
            return make_ready_future<>();
        }
        ++_server._stats._requests_serving;
        _pending_requests_gate.enter();
        utils::latency_counter lc;
        lc.start();
        auto leave = defer([this] { _pending_requests_gate.leave(); });
        return process_request_internal().then([this, leave = std::move(leave), lc = std::move(lc)] (auto&& result) mutable {
            --_server._stats._requests_serving;
            try {
                write_reply(std::move(result));
                ++_server._stats._requests_served;
                _server._stats._requests.mark(lc.stop().latency());
                if (lc.is_start()) {
                    _server._stats._estimated_requests_latency.add(lc.latency(), _server._stats._requests.hist.count);
                }
            } catch (...) {
                logging.error("request processing failed: {}", std::current_exception());
            }
        });
    });
}

static inline bytes_view to_bytes_view(temporary_buffer<char>& b)
{
    using byte = bytes_view::value_type;
    return bytes_view(reinterpret_cast<const byte*>(b.get()), b.size());
}

}

db::consistency_level make_consistency_level(const sstring& level)
{
    std::unordered_map<sstring, db::consistency_level> consistency_levels {
        {"ONE", db::consistency_level::ONE},
        {"QUORUM", db::consistency_level::QUORUM},
        {"LOCAL_QUORUM", db::consistency_level::LOCAL_QUORUM},
        {"EACH_QUORUM", db::consistency_level::EACH_QUORUM},
        {"ALL", db::consistency_level::ALL},
        {"ANY", db::consistency_level::ANY},
        {"TWO", db::consistency_level::TWO},
        {"THREE", db::consistency_level::THREE},
        {"SERIAL", db::consistency_level::SERIAL},
        {"LOCAL_SERIAL", db::consistency_level::LOCAL_SERIAL},
        {"LOCAL_ONE", db::consistency_level::LOCAL_ONE},
    };
    auto iter_cl = consistency_levels.find(level);
    if (iter_cl == consistency_levels.end()) {
        return db::consistency_level::ONE;
    }
    return iter_cl->second;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011, Blender Foundation.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "tile.h"

#include "util_algorithm.h"
#include "util_types.h"

CCL_NAMESPACE_BEGIN

TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_,
                         bool preserve_tile_device_, bool background_, int num_devices_)
{
	progressive = progressive_;
	tile_size = tile_size_;
	start_resolution = start_resolution_;
	num_devices = num_devices_;
	preserve_tile_device = preserve_tile_device_;
	background = background_;

	BufferParams buffer_params;
	reset(buffer_params, 0);
}

TileManager::~TileManager()
{
}

void TileManager::reset(BufferParams& params_, int num_samples_)
{
	params = params_;

	int divider = 1;
	int w = params.width, h = params.height;

	if(start_resolution != INT_MAX) {
		while(w*h > start_resolution*start_resolution) {
			w = max(1, w/2);
			h = max(1, h/2);

			divider *= 2;
		}
	}

	num_samples = num_samples_;

	state.buffer = BufferParams();
	state.sample = -1;
	state.num_tiles = 0;
	state.num_rendered_tiles = 0;
	state.num_samples = 0;
	state.resolution_divider = divider;
	state.tiles.clear();
}

void TileManager::set_samples(int num_samples_)
{
	num_samples = num_samples_;
}

/* splits image into tiles and assigns equal amount of tiles to every render device */
void TileManager::gen_tiles_global()
{
	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	state.tiles.clear();

	int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
	int tile_h = (tile_size.y >= image_h)? 1: (image_h + tile_size.y - 1)/tile_size.y;

	int num_logical_devices = preserve_tile_device? num_devices: 1;
	int num = min(image_h, num_logical_devices);
	int tile_index = 0;

	int tiles_per_device = (tile_w * tile_h + num - 1) / num;
	int cur_device = 0, cur_tiles = 0;

	for(int tile_y = 0; tile_y < tile_h; tile_y++) {
		for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) {
			int x = tile_x * tile_size.x;
			int y = tile_y * tile_size.y;
			int w = (tile_x == tile_w-1)? image_w - x: tile_size.x;
			int h = (tile_y == tile_h-1)? image_h - y: tile_size.y;

			state.tiles.push_back(Tile(tile_index, x, y, w, h, cur_device));
			cur_tiles++;

			if(cur_tiles == tiles_per_device) {
				cur_tiles = 0;
				cur_device++;
			}
		}
	}
}

/* slices image into as much pieces as how many devices are rendering this image */
void TileManager::gen_tiles_sliced()
{
	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	state.tiles.clear();

	int num_logical_devices = preserve_tile_device? num_devices: 1;
	int num = min(image_h, num_logical_devices);
	int tile_index = 0;

	for(int device = 0; device < num; device++) {
		int device_y = (image_h/num)*device;
		int device_h = (device == num-1)? image_h - device*(image_h/num): image_h/num;

		int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
		int tile_h = (tile_size.y >= device_h)? 1: (device_h + tile_size.y - 1)/tile_size.y;

		for(int tile_y = 0; tile_y < tile_h; tile_y++) {
			for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) {
				int x = tile_x * tile_size.x;
				int y = tile_y * tile_size.y;
				int w = (tile_x == tile_w-1)? image_w - x: tile_size.x;
				int h = (tile_y == tile_h-1)? device_h - y: tile_size.x;

				state.tiles.push_back(Tile(tile_index, x, y + device_y, w, h, device));
			}
		}
	}
}

void TileManager::set_tiles()
{
	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	if(background)
		gen_tiles_global();
	else
		gen_tiles_sliced();

	state.num_tiles = state.tiles.size();

	state.buffer.width = image_w;
	state.buffer.height = image_h;

	state.buffer.full_x = params.full_x/resolution;
	state.buffer.full_y = params.full_y/resolution;
	state.buffer.full_width = max(1, params.full_width/resolution);
	state.buffer.full_height = max(1, params.full_height/resolution);
}

list<Tile>::iterator TileManager::next_center_tile(int device)
{
	list<Tile>::iterator iter, best = state.tiles.end();

	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	int logical_device = preserve_tile_device? device: 0;

	int64_t centx = image_w / 2, centy = image_h / 2, tot = 1;
	int64_t mindist = (int64_t) image_w * (int64_t) image_h;

	/* find center of rendering tiles, image center counts for 1 too */
	for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
		if(iter->rendering) {
			Tile &cur_tile = *iter;
			centx += cur_tile.x + cur_tile.w / 2;
			centy += cur_tile.y + cur_tile.h / 2;
			tot++;
		}
	}

	centx /= tot;
	centy /= tot;

	/* closest of the non-rendering tiles */
	for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
		if(iter->device == logical_device && iter->rendering == false) {
			Tile &cur_tile = *iter;

			int64_t distx = centx - (cur_tile.x + cur_tile.w / 2);
			int64_t disty = centy - (cur_tile.y + cur_tile.h / 2);
			distx = (int64_t) sqrt((double)distx * distx + disty * disty);

			if(distx < mindist) {
				best = iter;
				mindist = distx;
			}
		}
	}

	return best;
}

list<Tile>::iterator TileManager::next_simple_tile(int device)
{
	list<Tile>::iterator iter;

	int logical_device = preserve_tile_device? device: 0;

	for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
		if(iter->device == logical_device && iter->rendering == false)
			return iter;
	}

	return state.tiles.end();
}

bool TileManager::next_tile(Tile& tile, int device)
{
	list<Tile>::iterator tile_it;

	if(background)
		tile_it = next_center_tile(device);
	else
		tile_it = next_simple_tile(device);

	if(tile_it != state.tiles.end()) {
		tile_it->rendering = true;
		tile = *tile_it;
		state.num_rendered_tiles++;

		return true;
	}

	return false;
}

bool TileManager::done()
{
	return (state.sample+state.num_samples >= num_samples && state.resolution_divider == 1);
}

bool TileManager::next()
{
	if(done())
		return false;

	if(progressive && state.resolution_divider > 1) {
		state.sample = 0;
		state.resolution_divider /= 2;
		state.num_samples = 1;
		set_tiles();
	}
	else {
		state.sample++;

		if(progressive)
			state.num_samples = 1;
		else
			state.num_samples = num_samples;

		state.resolution_divider = 1;
		set_tiles();
	}

	return true;
}

CCL_NAMESPACE_END

<commit_msg>Stupid copy-paste typo in tiles commit.<commit_after>/*
 * Copyright 2011, Blender Foundation.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "tile.h"

#include "util_algorithm.h"
#include "util_types.h"

CCL_NAMESPACE_BEGIN

TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_,
                         bool preserve_tile_device_, bool background_, int num_devices_)
{
	progressive = progressive_;
	tile_size = tile_size_;
	start_resolution = start_resolution_;
	num_devices = num_devices_;
	preserve_tile_device = preserve_tile_device_;
	background = background_;

	BufferParams buffer_params;
	reset(buffer_params, 0);
}

TileManager::~TileManager()
{
}

void TileManager::reset(BufferParams& params_, int num_samples_)
{
	params = params_;

	int divider = 1;
	int w = params.width, h = params.height;

	if(start_resolution != INT_MAX) {
		while(w*h > start_resolution*start_resolution) {
			w = max(1, w/2);
			h = max(1, h/2);

			divider *= 2;
		}
	}

	num_samples = num_samples_;

	state.buffer = BufferParams();
	state.sample = -1;
	state.num_tiles = 0;
	state.num_rendered_tiles = 0;
	state.num_samples = 0;
	state.resolution_divider = divider;
	state.tiles.clear();
}

void TileManager::set_samples(int num_samples_)
{
	num_samples = num_samples_;
}

/* splits image into tiles and assigns equal amount of tiles to every render device */
void TileManager::gen_tiles_global()
{
	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	state.tiles.clear();

	int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
	int tile_h = (tile_size.y >= image_h)? 1: (image_h + tile_size.y - 1)/tile_size.y;

	int num_logical_devices = preserve_tile_device? num_devices: 1;
	int num = min(image_h, num_logical_devices);
	int tile_index = 0;

	int tiles_per_device = (tile_w * tile_h + num - 1) / num;
	int cur_device = 0, cur_tiles = 0;

	for(int tile_y = 0; tile_y < tile_h; tile_y++) {
		for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) {
			int x = tile_x * tile_size.x;
			int y = tile_y * tile_size.y;
			int w = (tile_x == tile_w-1)? image_w - x: tile_size.x;
			int h = (tile_y == tile_h-1)? image_h - y: tile_size.y;

			state.tiles.push_back(Tile(tile_index, x, y, w, h, cur_device));
			cur_tiles++;

			if(cur_tiles == tiles_per_device) {
				cur_tiles = 0;
				cur_device++;
			}
		}
	}
}

/* slices image into as much pieces as how many devices are rendering this image */
void TileManager::gen_tiles_sliced()
{
	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	state.tiles.clear();

	int num_logical_devices = preserve_tile_device? num_devices: 1;
	int num = min(image_h, num_logical_devices);
	int tile_index = 0;

	for(int device = 0; device < num; device++) {
		int device_y = (image_h/num)*device;
		int device_h = (device == num-1)? image_h - device*(image_h/num): image_h/num;

		int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
		int tile_h = (tile_size.y >= device_h)? 1: (device_h + tile_size.y - 1)/tile_size.y;

		for(int tile_y = 0; tile_y < tile_h; tile_y++) {
			for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) {
				int x = tile_x * tile_size.x;
				int y = tile_y * tile_size.y;
				int w = (tile_x == tile_w-1)? image_w - x: tile_size.x;
				int h = (tile_y == tile_h-1)? device_h - y: tile_size.y;

				state.tiles.push_back(Tile(tile_index, x, y + device_y, w, h, device));
			}
		}
	}
}

void TileManager::set_tiles()
{
	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	if(background)
		gen_tiles_global();
	else
		gen_tiles_sliced();

	state.num_tiles = state.tiles.size();

	state.buffer.width = image_w;
	state.buffer.height = image_h;

	state.buffer.full_x = params.full_x/resolution;
	state.buffer.full_y = params.full_y/resolution;
	state.buffer.full_width = max(1, params.full_width/resolution);
	state.buffer.full_height = max(1, params.full_height/resolution);
}

list<Tile>::iterator TileManager::next_center_tile(int device)
{
	list<Tile>::iterator iter, best = state.tiles.end();

	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	int logical_device = preserve_tile_device? device: 0;

	int64_t centx = image_w / 2, centy = image_h / 2, tot = 1;
	int64_t mindist = (int64_t) image_w * (int64_t) image_h;

	/* find center of rendering tiles, image center counts for 1 too */
	for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
		if(iter->rendering) {
			Tile &cur_tile = *iter;
			centx += cur_tile.x + cur_tile.w / 2;
			centy += cur_tile.y + cur_tile.h / 2;
			tot++;
		}
	}

	centx /= tot;
	centy /= tot;

	/* closest of the non-rendering tiles */
	for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
		if(iter->device == logical_device && iter->rendering == false) {
			Tile &cur_tile = *iter;

			int64_t distx = centx - (cur_tile.x + cur_tile.w / 2);
			int64_t disty = centy - (cur_tile.y + cur_tile.h / 2);
			distx = (int64_t) sqrt((double)distx * distx + disty * disty);

			if(distx < mindist) {
				best = iter;
				mindist = distx;
			}
		}
	}

	return best;
}

list<Tile>::iterator TileManager::next_simple_tile(int device)
{
	list<Tile>::iterator iter;

	int logical_device = preserve_tile_device? device: 0;

	for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
		if(iter->device == logical_device && iter->rendering == false)
			return iter;
	}

	return state.tiles.end();
}

bool TileManager::next_tile(Tile& tile, int device)
{
	list<Tile>::iterator tile_it;

	if(background)
		tile_it = next_center_tile(device);
	else
		tile_it = next_simple_tile(device);

	if(tile_it != state.tiles.end()) {
		tile_it->rendering = true;
		tile = *tile_it;
		state.num_rendered_tiles++;

		return true;
	}

	return false;
}

bool TileManager::done()
{
	return (state.sample+state.num_samples >= num_samples && state.resolution_divider == 1);
}

bool TileManager::next()
{
	if(done())
		return false;

	if(progressive && state.resolution_divider > 1) {
		state.sample = 0;
		state.resolution_divider /= 2;
		state.num_samples = 1;
		set_tiles();
	}
	else {
		state.sample++;

		if(progressive)
			state.num_samples = 1;
		else
			state.num_samples = num_samples;

		state.resolution_divider = 1;
		set_tiles();
	}

	return true;
}

CCL_NAMESPACE_END

<|endoftext|>


<commit_before>#pragma once

#include "constants.hpp"
#include "libkrbn/libkrbn.h"
#include "logger.hpp"
#include <pqrs/spdlog.hpp>

class libkrbn_log_lines_class final {
public:
  libkrbn_log_lines_class(std::shared_ptr<std::deque<std::string>> lines) : lines_(lines) {
  }

  std::shared_ptr<std::deque<std::string>> get_lines(void) const {
    return lines_;
  }

private:
  std::shared_ptr<std::deque<std::string>> lines_;
};

class libkrbn_log_monitor final {
public:
  libkrbn_log_monitor(const libkrbn_log_monitor&) = delete;

  libkrbn_log_monitor(libkrbn_log_monitor_callback callback,
                      void* refcon) {
    krbn::logger::get_logger()->info(__func__);

    std::vector<std::string> targets = {
        "/var/log/karabiner/observer.log",
        "/var/log/karabiner/grabber.log",
        fmt::format("/var/log/karabiner/session_monitor.{0}.log", geteuid()),
    };
    auto log_directory = krbn::constants::get_user_log_directory();
    if (!log_directory.empty()) {
      targets.push_back(log_directory + "/console_user_server.log");
    }

    monitor_ = std::make_unique<pqrs::spdlog::monitor>(pqrs::dispatcher::extra::get_shared_dispatcher(),
                                                       targets,
                                                       250);

    monitor_->log_file_updated.connect([callback, refcon](auto&& lines) {
      if (callback) {
        auto log_lines = new libkrbn_log_lines_class(lines);
        callback(reinterpret_cast<libkrbn_log_lines*>(log_lines), refcon);
        delete log_lines;
      }
    });

    monitor_->async_start(std::chrono::milliseconds(1000));
  }

  ~libkrbn_log_monitor(void) {
    krbn::logger::get_logger()->info(__func__);
  }

private:
  std::unique_ptr<pqrs::spdlog::monitor> monitor_;
};
<commit_msg>add kextd.log to libkrbn_log_monitor<commit_after>#pragma once

#include "constants.hpp"
#include "libkrbn/libkrbn.h"
#include "logger.hpp"
#include <pqrs/spdlog.hpp>

class libkrbn_log_lines_class final {
public:
  libkrbn_log_lines_class(std::shared_ptr<std::deque<std::string>> lines) : lines_(lines) {
  }

  std::shared_ptr<std::deque<std::string>> get_lines(void) const {
    return lines_;
  }

private:
  std::shared_ptr<std::deque<std::string>> lines_;
};

class libkrbn_log_monitor final {
public:
  libkrbn_log_monitor(const libkrbn_log_monitor&) = delete;

  libkrbn_log_monitor(libkrbn_log_monitor_callback callback,
                      void* refcon) {
    krbn::logger::get_logger()->info(__func__);

    std::vector<std::string> targets = {
        "/var/log/karabiner/kextd.log",
        "/var/log/karabiner/grabber.log",
        "/var/log/karabiner/observer.log",
        fmt::format("/var/log/karabiner/session_monitor.{0}.log", geteuid()),
    };
    auto log_directory = krbn::constants::get_user_log_directory();
    if (!log_directory.empty()) {
      targets.push_back(log_directory + "/console_user_server.log");
    }

    monitor_ = std::make_unique<pqrs::spdlog::monitor>(pqrs::dispatcher::extra::get_shared_dispatcher(),
                                                       targets,
                                                       250);

    monitor_->log_file_updated.connect([callback, refcon](auto&& lines) {
      if (callback) {
        auto log_lines = new libkrbn_log_lines_class(lines);
        callback(reinterpret_cast<libkrbn_log_lines*>(log_lines), refcon);
        delete log_lines;
      }
    });

    monitor_->async_start(std::chrono::milliseconds(1000));
  }

  ~libkrbn_log_monitor(void) {
    krbn::logger::get_logger()->info(__func__);
  }

private:
  std::unique_ptr<pqrs::spdlog::monitor> monitor_;
};
<|endoftext|>


<commit_before>/**
 * \file Poisson.cpp
 * \brief
 *
 * Poisson disk points generator
 *
 * \version 1.0
 * \date 06/05/2014
 * \author Sergey Kosarevsky, 2014
 * \author support@linderdaum.com http://www.linderdaum.com
 */

/*
	To compile:
		gcc Poisson.cpp -std=c++11 -lstdc++
*/

// Fast Poisson Disk Sampling in Arbitrary Dimensions
// http://people.cs.ubc.ca/~rbridson/docs/bridson-siggraph07-poissondisk.pdf

// Implementation based on http://devmag.org.za/2009/05/03/poisson-disk-sampling/

#include <iostream>
#include <vector>
#include <random>
#include <stdint.h>
#include <fstream>
#include <memory.h>

///////////////// User selectable parameters ///////////////////////////////

const int   NumPoints   = 20000;	// minimal number of points to generate
const bool  Circle      = true;	// 'true' to fill a circle, 'false' to fill a rectangle
const int   ImageSize   = 1024;	// generate RGB image [ImageSize x ImageSize]
const int   k           = 30;		// refer to bridson-siggraph07-poissondisk.pdf for details

////////////////////////////////////////////////////////////////////////////

const char* Version = "1.0 (06/05/2014)";

const float MinDistance = sqrt( float(NumPoints) ) / float(NumPoints);

std::random_device rd;
std::mt19937 gen( rd() );
std::uniform_real_distribution<> dis( 0.0, 1.0 );

struct sPoint
{
	sPoint(): Valid( false ) {}
	sPoint( float X, float Y )
		: x( X )
		, y( Y )
		, Valid( true )
	{}
	float x;
	float y;
	bool Valid;
	//
	bool IsInRectangle() const
	{
		return x >= 0 && y >= 0 && x <= 1 && y <= 1;
	}
	//
	bool IsInCircle() const
	{
		float fx = x - 0.5f;
		float fy = y - 0.5f;
		return ( fx*fx + fy*fy ) <= 0.25f;
	}
};

struct sGridPoint
{
	sGridPoint( int X, int Y )
		: x( X )
		, y( Y )
	{}
	int x;
	int y;
};

float RandomFloat()
{
	return static_cast<float>( dis( gen ) );
}

float GetDistance( const sPoint& P1, const sPoint& P2 )
{
	return sqrt( ( P1.x - P2.x ) * ( P1.x - P2.x ) + ( P1.y - P2.y ) * ( P1.y - P2.y ) );
}

sGridPoint ImageToGrid( const sPoint& P, float CellSize )
{
	return sGridPoint( ( int )( P.x / CellSize ), ( int )( P.y / CellSize ) );
}

struct sGrid
{
	sGrid( int W, int H, float CellSize )
		: m_W( W )
		, m_H( H )
		, m_CellSize( CellSize )
	{
		m_Grid.resize( m_H );

		for ( auto i = m_Grid.begin(); i != m_Grid.end(); i++ ) { i->resize( m_W ); }
	}
	void Insert( const sPoint& P )
	{
		sGridPoint G = ImageToGrid( P, m_CellSize );
		m_Grid[G.x][G.y] = P;
	}
	bool IsInNeighbourhood( sPoint Point, float MinDist, float CellSize )
	{
		sGridPoint G = ImageToGrid( Point, CellSize );

		// number of adjucent cells to look for neighbour points
		int D = 5;

		// scan the neighbourhood of the point in the grid
		for ( int i = G.x - D; i < G.x + D; i++ )
		{
			for ( int j = G.y - D; j < G.y + D; j++ )
			{
				if ( i >= 0 && i < m_W && j >= 0 && j < m_H )
				{
					sPoint P = m_Grid[i][j];

					if ( P.Valid && GetDistance( P, Point ) < MinDist ) { return true; }
				}
			}
		}

		return false;
	}

private:
	int m_W;
	int m_H;
	float m_CellSize;

	std::vector< std::vector<sPoint> > m_Grid;
};

sPoint PopRandom( std::vector<sPoint>& Points )
{
	std::uniform_int_distribution<> dis( 0, Points.size() - 1 );
	int Idx = dis( gen );
	sPoint P = Points[ Idx ];
	Points.erase( Points.begin() + Idx );
	return P;
}

sPoint GenerateRandomPointAround( const sPoint& P, float MinDist )
{
	// start with non-uniform distribution
	float R1 = RandomFloat();
	float R2 = RandomFloat();

	// radius should be between MinDist and 2 * MinDist
	float Radius = MinDist * ( R1 + 1.0f );

	// random angle
	float Angle = 2 * 3.141592653589f * R2;

	// the new point is generated around the point (x, y)
	float X = P.x + Radius * cos( Angle );
	float Y = P.y + Radius * sin( Angle );

	return sPoint( X, Y );
}

std::vector<sPoint> GeneratePoissonPoints( float MinDist, int NewPointsCount, size_t NumPoints )
{
	std::vector<sPoint> SamplePoints;
	std::vector<sPoint> ProcessList;

	// create the grid
	float CellSize = MinDist / sqrt( 2.0f );

	int GridW = ( int )ceil( 1.0f / CellSize );
	int GridH = ( int )ceil( 1.0f / CellSize );

	sGrid Grid( GridW, GridH, CellSize );

	sPoint FirstPoint = sPoint( RandomFloat(), RandomFloat() );

	// update containers
	ProcessList.push_back( FirstPoint );
	SamplePoints.push_back( FirstPoint );
	Grid.Insert( FirstPoint );

	// generate new points for each point in the queue
	while ( !ProcessList.empty() && SamplePoints.size() < NumPoints )
	{
		// a progress indicator, kind of
		if ( SamplePoints.size() % 100 == 0 ) std::cout << ".";

		sPoint Point = PopRandom( ProcessList );

		for ( int i = 0; i < NewPointsCount; i++ )
		{
			sPoint NewPoint = GenerateRandomPointAround( Point, MinDist );

			bool Fits = Circle ? NewPoint.IsInCircle() : NewPoint.IsInRectangle();

			if ( Fits && !Grid.IsInNeighbourhood( NewPoint, MinDist, CellSize ) )
			{
				ProcessList.push_back( NewPoint );
				SamplePoints.push_back( NewPoint );
				Grid.Insert( NewPoint );
				continue;
			}
		}
	}

	std::cout << std::endl << std::endl;

	return SamplePoints;
}

#if defined( __GNUC__ )
#	define GCC_PACK(n) __attribute__((packed,aligned(n)))
#else
#	define GCC_PACK(n) __declspec(align(n))
#endif // __GNUC__

#pragma pack(push, 1)
struct GCC_PACK( 1 ) sBMPHeader
{
   // BITMAPFILEHEADER
   unsigned short    bfType;
   uint32_t          bfSize;
   unsigned short    bfReserved1;
   unsigned short    bfReserved2;
   uint32_t          bfOffBits;
   // BITMAPINFOHEADER
   uint32_t          biSize;
   uint32_t          biWidth;
   uint32_t          biHeight;
   unsigned short    biPlanes;
   unsigned short    biBitCount;
   uint32_t          biCompression;
   uint32_t          biSizeImage;
   uint32_t          biXPelsPerMeter;
   uint32_t          biYPelsPerMeter;
   uint32_t          biClrUsed;
   uint32_t          biClrImportant;
};
#pragma pack(pop)

void SaveBMP( const char* FileName, const void* RawBGRImage, int Width, int Height )
{
	sBMPHeader Header;

	int ImageSize = Width * Height * 3;

	Header.bfType          = 0x4D * 256 + 0x42;
	Header.bfSize          = ImageSize + sizeof( sBMPHeader );
	Header.bfReserved1     = 0;
	Header.bfReserved2     = 0;
	Header.bfOffBits       = 0x36;
	Header.biSize          = 40;
	Header.biWidth         = Width;
	Header.biHeight        = Height;
	Header.biPlanes        = 1;
	Header.biBitCount      = 24;
	Header.biCompression   = 0;
	Header.biSizeImage     = ImageSize;
	Header.biXPelsPerMeter = 6000;
	Header.biYPelsPerMeter = 6000;
	Header.biClrUsed       = 0;
	Header.biClrImportant  = 0;

	std::ofstream File( FileName, std::ios::out | std::ios::binary );

	File.write( (const char*)&Header, sizeof( Header ) );
	File.write( (const char*)RawBGRImage, ImageSize );

	std::cout << "Saved " << FileName << std::endl;
}

void PrintBanner()
{
	std::cout << "Poisson disk points generator" << std::endl;
	std::cout << "Version " << Version << std::endl;
	std::cout << "Sergey Kosarevsky, 2014" << std::endl;
	std::cout << "support@linderdaum.com http://www.linderdaum.com" << std::endl;
	std::cout << std::endl;
}

int main()
{
	PrintBanner();

	std::vector<sPoint> Points = GeneratePoissonPoints( MinDistance, k, NumPoints );

	// prepare BGR image
	size_t DataSize = 3*ImageSize*ImageSize;

	unsigned char* Img = new unsigned char[ DataSize ];

	memset( Img, 0, DataSize );

	for ( auto i = Points.begin(); i != Points.end(); i++ )
	{
		int x = int( i->x * ImageSize );
		int y = int( i->y * ImageSize );
		int Base = 3 * (x + y * ImageSize);
		Img[ Base+0 ] = Img[ Base+1 ] = Img[ Base+2 ] = 255;
	}

	SaveBMP( "Poisson.bmp", Img, ImageSize, ImageSize );

	delete[] Img;

	return 0;
}
<commit_msg>Density map loading (uncompressed bitmap)<commit_after>/**
 * \file Poisson.cpp
 * \brief
 *
 * Poisson Disk Points Generator
 *
 * \version 1.1.0
 * \date 07/05/2014
 * \author Sergey Kosarevsky, 2014
 * \author support@linderdaum.com http://www.linderdaum.com
 */

/*
	To compile:
		gcc Poisson.cpp -std=c++11 -lstdc++
*/

// Fast Poisson Disk Sampling in Arbitrary Dimensions
// http://people.cs.ubc.ca/~rbridson/docs/bridson-siggraph07-poissondisk.pdf

// Implementation based on http://devmag.org.za/2009/05/03/poisson-disk-sampling/

#include <iostream>
#include <vector>
#include <random>
#include <stdint.h>
#include <fstream>
#include <memory.h>

///////////////// User selectable parameters ///////////////////////////////

const int   NumPoints   = 20000;	// minimal number of points to generate
const bool  Circle      = true;	// 'true' to fill a circle, 'false' to fill a rectangle
const int   ImageSize   = 1024;	// generate RGB image [ImageSize x ImageSize]
const int   k           = 30;		// refer to bridson-siggraph07-poissondisk.pdf for details

////////////////////////////////////////////////////////////////////////////

const char* Version = "1.1.0 (07/05/2014)";

const float MinDistance = sqrt( float(NumPoints) ) / float(NumPoints);

std::random_device rd;
std::mt19937 gen( rd() );
std::uniform_real_distribution<> dis( 0.0, 1.0 );

float* g_DensityMap = NULL;

struct sPoint
{
	sPoint(): Valid( false ) {}
	sPoint( float X, float Y )
		: x( X )
		, y( Y )
		, Valid( true )
	{}
	float x;
	float y;
	bool Valid;
	//
	bool IsInRectangle() const
	{
		return x >= 0 && y >= 0 && x <= 1 && y <= 1;
	}
	//
	bool IsInCircle() const
	{
		float fx = x - 0.5f;
		float fy = y - 0.5f;
		return ( fx*fx + fy*fy ) <= 0.25f;
	}
};

struct sGridPoint
{
	sGridPoint( int X, int Y )
		: x( X )
		, y( Y )
	{}
	int x;
	int y;
};

float RandomFloat()
{
	return static_cast<float>( dis( gen ) );
}

float GetDistance( const sPoint& P1, const sPoint& P2 )
{
	return sqrt( ( P1.x - P2.x ) * ( P1.x - P2.x ) + ( P1.y - P2.y ) * ( P1.y - P2.y ) );
}

sGridPoint ImageToGrid( const sPoint& P, float CellSize )
{
	return sGridPoint( ( int )( P.x / CellSize ), ( int )( P.y / CellSize ) );
}

struct sGrid
{
	sGrid( int W, int H, float CellSize )
		: m_W( W )
		, m_H( H )
		, m_CellSize( CellSize )
	{
		m_Grid.resize( m_H );

		for ( auto i = m_Grid.begin(); i != m_Grid.end(); i++ ) { i->resize( m_W ); }
	}
	void Insert( const sPoint& P )
	{
		sGridPoint G = ImageToGrid( P, m_CellSize );
		m_Grid[G.x][G.y] = P;
	}
	bool IsInNeighbourhood( sPoint Point, float MinDist, float CellSize )
	{
		sGridPoint G = ImageToGrid( Point, CellSize );

		// number of adjucent cells to look for neighbour points
		int D = 5;

		// scan the neighbourhood of the point in the grid
		for ( int i = G.x - D; i < G.x + D; i++ )
		{
			for ( int j = G.y - D; j < G.y + D; j++ )
			{
				if ( i >= 0 && i < m_W && j >= 0 && j < m_H )
				{
					sPoint P = m_Grid[i][j];

					if ( P.Valid && GetDistance( P, Point ) < MinDist ) { return true; }
				}
			}
		}

		return false;
	}

private:
	int m_W;
	int m_H;
	float m_CellSize;

	std::vector< std::vector<sPoint> > m_Grid;
};

sPoint PopRandom( std::vector<sPoint>& Points )
{
	std::uniform_int_distribution<> dis( 0, Points.size() - 1 );
	int Idx = dis( gen );
	sPoint P = Points[ Idx ];
	Points.erase( Points.begin() + Idx );
	return P;
}

sPoint GenerateRandomPointAround( const sPoint& P, float MinDist )
{
	// start with non-uniform distribution
	float R1 = RandomFloat();
	float R2 = RandomFloat();

	// radius should be between MinDist and 2 * MinDist
	float Radius = MinDist * ( R1 + 1.0f );

	// random angle
	float Angle = 2 * 3.141592653589f * R2;

	// the new point is generated around the point (x, y)
	float X = P.x + Radius * cos( Angle );
	float Y = P.y + Radius * sin( Angle );

	return sPoint( X, Y );
}

std::vector<sPoint> GeneratePoissonPoints( float MinDist, int NewPointsCount, size_t NumPoints )
{
	std::vector<sPoint> SamplePoints;
	std::vector<sPoint> ProcessList;

	// create the grid
	float CellSize = MinDist / sqrt( 2.0f );

	int GridW = ( int )ceil( 1.0f / CellSize );
	int GridH = ( int )ceil( 1.0f / CellSize );

	sGrid Grid( GridW, GridH, CellSize );

	sPoint FirstPoint = sPoint( RandomFloat(), RandomFloat() );

	// update containers
	ProcessList.push_back( FirstPoint );
	SamplePoints.push_back( FirstPoint );
	Grid.Insert( FirstPoint );

	// generate new points for each point in the queue
	while ( !ProcessList.empty() && SamplePoints.size() < NumPoints )
	{
		// a progress indicator, kind of
		if ( SamplePoints.size() % 100 == 0 ) std::cout << ".";

		sPoint Point = PopRandom( ProcessList );

		for ( int i = 0; i < NewPointsCount; i++ )
		{
			sPoint NewPoint = GenerateRandomPointAround( Point, MinDist );

			bool Fits = Circle ? NewPoint.IsInCircle() : NewPoint.IsInRectangle();

			if ( Fits && !Grid.IsInNeighbourhood( NewPoint, MinDist, CellSize ) )
			{
				ProcessList.push_back( NewPoint );
				SamplePoints.push_back( NewPoint );
				Grid.Insert( NewPoint );
				continue;
			}
		}
	}

	std::cout << std::endl << std::endl;

	return SamplePoints;
}

#if defined( __GNUC__ )
#	define GCC_PACK(n) __attribute__((packed,aligned(n)))
#else
#	define GCC_PACK(n) __declspec(align(n))
#endif // __GNUC__

#pragma pack(push, 1)
struct GCC_PACK( 1 ) sBMPHeader
{
   // BITMAPFILEHEADER
   unsigned short    bfType;
   uint32_t          bfSize;
   unsigned short    bfReserved1;
   unsigned short    bfReserved2;
   uint32_t          bfOffBits;
   // BITMAPINFOHEADER
   uint32_t          biSize;
   uint32_t          biWidth;
   uint32_t          biHeight;
   unsigned short    biPlanes;
   unsigned short    biBitCount;
   uint32_t          biCompression;
   uint32_t          biSizeImage;
   uint32_t          biXPelsPerMeter;
   uint32_t          biYPelsPerMeter;
   uint32_t          biClrUsed;
   uint32_t          biClrImportant;
};
#pragma pack(pop)

void SaveBMP( const char* FileName, const void* RawBGRImage, int Width, int Height )
{
	sBMPHeader Header;

	int ImageSize = Width * Height * 3;

	Header.bfType          = 0x4D * 256 + 0x42;
	Header.bfSize          = ImageSize + sizeof( sBMPHeader );
	Header.bfReserved1     = 0;
	Header.bfReserved2     = 0;
	Header.bfOffBits       = 0x36;
	Header.biSize          = 40;
	Header.biWidth         = Width;
	Header.biHeight        = Height;
	Header.biPlanes        = 1;
	Header.biBitCount      = 24;
	Header.biCompression   = 0;
	Header.biSizeImage     = ImageSize;
	Header.biXPelsPerMeter = 6000;
	Header.biYPelsPerMeter = 6000;
	Header.biClrUsed       = 0;
	Header.biClrImportant  = 0;

	std::ofstream File( FileName, std::ios::out | std::ios::binary );

	File.write( (const char*)&Header, sizeof( Header ) );
	File.write( (const char*)RawBGRImage, ImageSize );

	std::cout << "Saved " << FileName << std::endl;
}

unsigned char* LoadBMP( const char* FileName, int* OutWidth, int* OutHeight )
{
	sBMPHeader Header;

	std::ifstream File( FileName, std::ifstream::binary );

	File.read( (char*)&Header, sizeof( Header ) );

	*OutWidth  = Header.biWidth;
	*OutHeight = Header.biHeight;

	size_t DataSize = 3 * Header.biWidth * Header.biHeight;

	unsigned char* Img = new unsigned char[ DataSize ];

	File.read( (char*)Img, DataSize );

	return Img;
}

void LoadDensityMap( const char* FileName )
{
	std::cout << "Loading density map " << FileName << std::endl;

	int W, H;
	unsigned char* Data = LoadBMP( FileName, &W, &H );

	std::cout << "Loaded ( " << W << " x " << H << " ) " << std::endl;

	if ( W != ImageSize || H != ImageSize )
	{
		std::cout << "ERROR: density map should be " << ImageSize << " x " << ImageSize << std::endl;

		exit( 255 );
	}

	g_DensityMap = new float[ W * H ];

	for ( int y = 0; y != H; y++ )
	{
		for ( int x = 0; x != W; x++ )
		{
			g_DensityMap[ x + y * W ] = float( Data[ 3 * (x + y * W) ] ) / 255.0f;
		}
	}

	delete[]( Data );
}

void PrintBanner()
{
	std::cout << "Poisson disk points generator" << std::endl;
	std::cout << "Version " << Version << std::endl;
	std::cout << "Sergey Kosarevsky, 2014" << std::endl;
	std::cout << "support@linderdaum.com http://www.linderdaum.com" << std::endl;
	std::cout << std::endl;
	std::cout << "Usage: Poisson [density-map-rgb24.bmp]" << std::endl;
	std::cout << std::endl;
}

int main( int argc, char** argv )
{
	PrintBanner();

	if ( argc > 1 )
	{
		LoadDensityMap( argv[1] );
	}

	std::vector<sPoint> Points = GeneratePoissonPoints( MinDistance, k, NumPoints );

	// prepare BGR image
	size_t DataSize = 3 * ImageSize * ImageSize;

	unsigned char* Img = new unsigned char[ DataSize ];

	memset( Img, 0, DataSize );

	for ( auto i = Points.begin(); i != Points.end(); i++ )
	{
		int x = int( i->x * ImageSize );
		int y = int( i->y * ImageSize );
		if ( g_DensityMap )
		{
			// dice
			float R = RandomFloat();
			float P = g_DensityMap[ x + y * ImageSize ];
			if ( R > P ) continue;
		}
		int Base = 3 * (x + y * ImageSize);
		Img[ Base+0 ] = Img[ Base+1 ] = Img[ Base+2 ] = 255;
	}

	SaveBMP( "Poisson.bmp", Img, ImageSize, ImageSize );

	delete[]( Img );

	return 0;
}
<|endoftext|>


<commit_before>// http://algospot.com/judge/problem/read/CLOCKSYNC
#include <iostream>
#include <cstdio>

using namespace std;

int sw [] = { // switch
    7,      //    {0, 1, 2},
    2696,   //    {3, 7, 9, 11},
    50192,  //    {4, 10, 14, 15},
    241,    //    {0, 4, 5, 6, 7},
    5568,   //    {6, 7, 8, 10, 12},
    49157,  //    {0, 2, 14, 15},
    49160,  //    {3, 14, 15},
    49328,  //    {4, 5, 7, 14, 15},
    62,     //    {1, 2, 3, 4, 5},
    8760    //    {3, 4, 5, 9, 13}
};

unsigned int state;
int n;

void getInput() {
    int in;
    state = 0;
    for (int i = 0; i < 16; i++) {
        cin >> in;
        in = (in / 3) % 4;
        state |= (in & 0x3) << (i * 2);
    }
}

unsigned int move(int index, unsigned int st) {
    int r = sw[index];
    while (r) {
        int i = __builtin_ctz(r) * 2;
        r &= r - 1;

        int current = st & (0x3 << i);
        current +=
        st &= ~(0x3 << i);
        st |= ;
    }
}

void solve() {
    for (int i = 0; i < 10; i++) {
    }
}

int main() {
    int num;
    cin >> num;
    for (int i = 0; i < num; i++) {getInput(); solve();}
    return 0;
}
<commit_msg>not completed<commit_after>// http://algospot.com/judge/problem/read/CLOCKSYNC
#include <iostream>

using namespace std;

int sw [] = { // switch
    7,      //    {0, 1, 2},
    2696,   //    {3, 7, 9, 11},
    50192,  //    {4, 10, 14, 15},
    241,    //    {0, 4, 5, 6, 7},
    5568,   //    {6, 7, 8, 10, 12},
    49157,  //    {0, 2, 14, 15},
    49160,  //    {3, 14, 15},
    49328,  //    {4, 5, 7, 14, 15},
    62,     //    {1, 2, 3, 4, 5},
    8760    //    {3, 4, 5, 9, 13}
};

unsigned int state;
int n;
int count;

void getInput() {
    int in;
    state = 0;
    for (int i = 0; i < 16; i++) {
        cin >> in;
        in = (in / 3) % 4;
        state |= (in & 0x3) << (i * 2);
    }
}

unsigned int move(int index, unsigned int st) {
    int r = sw[index];
    while (r) {
        int i = __builtin_ctz(r) * 2;
        r &= r - 1;

        int current = st + (0x1 << i);
        st &= ~(0x3 << i);
        st |= current & (0x3 << i);
    }
    return st;
}

void test(int c, int index, int st) {
    if (c >= count) return;
    if (index == 10) return;
    if (st == 0) {
        count = c;
        return;
    }

    for (int i = 0; i < 4; i++) {
        test(c + i, index + 1, st);
        st = move(index, st);
    }
}

void solve() {
    count = 500;
    unsigned int st = state;
    for (int i = 0; i < 4; i++) {
        test(i, 0, st);
        st = move(0, st);
    }

    if (count == 500) count = -1;
    cout << count << endl;
}

int main() {
    int num;
    cin >> num;
    for (int i = 0; i < num; i++) {getInput(); solve();}
    return 0;
}
<|endoftext|>