<commit_before>/*
 * Web Application Socket protocol, input data channel library.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_PROXY_WAS_INPUT_HXX
#define BENG_PROXY_WAS_INPUT_HXX

#include "glibfwd.hxx"

#include <stdint.h>

struct pool;
class Istream;
class WasInput;

struct WasInputHandler {
    /**
     * Istream::Close() has been called.
     */
    void (*close)(void *ctx);

    /**
     * All data was received from the pipe to the input buffer; we
     * don't need the pipe anymore for this request.
     *
     * Optional method.
     */
    void (*release)(void *ctx);

    void (*eof)(void *ctx);

    /**
     * The input was aborted prematurely, but the socket may be
     * reused.
     */
    void (*premature)(void *ctx);

    void (*abort)(void *ctx);
};

WasInput *
was_input_new(struct pool *pool, int fd,
              const WasInputHandler *handler, void *handler_ctx);

/**
 * @param error the error reported to the istream handler
 */
void
was_input_free(WasInput *input, GError *error);

static inline void
was_input_free_p(WasInput **input_p, GError *error)
{
    WasInput *input = *input_p;
    *input_p = nullptr;
    was_input_free(input, error);
}

/**
 * Like was_input_free(), but assumes that was_input_enable() has not
 * been called yet (no istream handler).
 */
void
was_input_free_unused(WasInput *input);

static inline void
was_input_free_unused_p(WasInput **input_p)
{
    WasInput *input = *input_p;
    *input_p = nullptr;
    was_input_free_unused(input);
}

Istream &
was_input_enable(WasInput &input);

/**
 * Set the new content length of this entity.
 *
 * @return false if the value is invalid (callback "abort" has been
 * invoked in this case)
 */
bool
was_input_set_length(WasInput *input, uint64_t length);

/**
 * Signals premature end of this stream.
 *
 * @param length the total number of bytes the peer has written to the
 * pipe
 * @return false if the object has been closed
 */
bool
was_input_premature(WasInput *input, uint64_t length);

void
was_input_enable_timeout(WasInput *input);

bool
was_input_discard_output(WasInput *input);

#endif
<commit_msg>was/input: remove obsolete prototype<commit_after>/*
 * Web Application Socket protocol, input data channel library.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_PROXY_WAS_INPUT_HXX
#define BENG_PROXY_WAS_INPUT_HXX

#include "glibfwd.hxx"

#include <stdint.h>

struct pool;
class Istream;
class WasInput;

struct WasInputHandler {
    /**
     * Istream::Close() has been called.
     */
    void (*close)(void *ctx);

    /**
     * All data was received from the pipe to the input buffer; we
     * don't need the pipe anymore for this request.
     *
     * Optional method.
     */
    void (*release)(void *ctx);

    void (*eof)(void *ctx);

    /**
     * The input was aborted prematurely, but the socket may be
     * reused.
     */
    void (*premature)(void *ctx);

    void (*abort)(void *ctx);
};

WasInput *
was_input_new(struct pool *pool, int fd,
              const WasInputHandler *handler, void *handler_ctx);

/**
 * @param error the error reported to the istream handler
 */
void
was_input_free(WasInput *input, GError *error);

static inline void
was_input_free_p(WasInput **input_p, GError *error)
{
    WasInput *input = *input_p;
    *input_p = nullptr;
    was_input_free(input, error);
}

/**
 * Like was_input_free(), but assumes that was_input_enable() has not
 * been called yet (no istream handler).
 */
void
was_input_free_unused(WasInput *input);

static inline void
was_input_free_unused_p(WasInput **input_p)
{
    WasInput *input = *input_p;
    *input_p = nullptr;
    was_input_free_unused(input);
}

Istream &
was_input_enable(WasInput &input);

/**
 * Set the new content length of this entity.
 *
 * @return false if the value is invalid (callback "abort" has been
 * invoked in this case)
 */
bool
was_input_set_length(WasInput *input, uint64_t length);

/**
 * Signals premature end of this stream.
 *
 * @param length the total number of bytes the peer has written to the
 * pipe
 * @return false if the object has been closed
 */
bool
was_input_premature(WasInput *input, uint64_t length);

void
was_input_enable_timeout(WasInput *input);

#endif
<|endoftext|>


<commit_before>// $Id: metis_partitioner.C,v 1.21 2005-09-09 12:26:51 jwpeterson Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2005  Benjamin S. Kirk, John W. Peterson

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ Includes   -----------------------------------

// Local Includes -----------------------------------
#include "libmesh_config.h"
#include "mesh_base.h"
#include "metis_partitioner.h"
#include "libmesh_logging.h"
#include "elem.h"

#ifdef HAVE_METIS
  namespace Metis {
    extern "C" {
#     include "metis.h"
    }
  }
#else
#  include "sfc_partitioner.h"
#endif

// ------------------------------------------------------------
// MetisPartitioner implementation
void MetisPartitioner::_do_partition (MeshBase& mesh,
				      const unsigned int n_pieces)
{
  assert (n_pieces > 0);

  // Check for an easy return
  if (n_pieces == 1)
    {
      this->single_partition (mesh);
      return;
    }

// What to do if the Metis library IS NOT present
#ifndef HAVE_METIS

  here();
  std::cerr << "ERROR: The library has been built without"    << std::endl
	    << "Metis support.  Using a space-filling curve"  << std::endl
	    << "partitioner instead!"                         << std::endl;

  SFCPartitioner sfcp;

  sfcp.partition (mesh, n_pieces);

// What to do if the Metis library IS present
#else

  START_LOG("partition()", "MetisPartitioner");

  const unsigned int n_active_elem = mesh.n_active_elem();
  const unsigned int n_elem        = mesh.n_elem();

  // build the graph
  // the forward_map maps each active element id
  // into a contiguous block of indices for Metis
  std::vector<unsigned int> forward_map (n_elem, libMesh::invalid_uint);

  std::vector<int> xadj;
  std::vector<int> adjncy;
  std::vector<int> options(5);
  std::vector<int> vwgt(n_active_elem);
  std::vector<int> part(n_active_elem);

  xadj.reserve(n_active_elem+1);

  int
    n = static_cast<int>(n_active_elem),  // number of "nodes" (elements)
                                          //   in the graph
    wgtflag = 2,                          // weights on vertices only,
                                          //   none on edges
    numflag = 0,                          // C-style 0-based numbering
    nparts  = static_cast<int>(n_pieces), // number of subdomains to create
    edgecut = 0;                          // the numbers of edges cut by the
                                          //   resulting partition

  // Set the options
  options[0] = 0; // use default options

  // Metis will only consider the active elements.
  // We need to map the active element ids into a
  // contiguous range.
  {

    MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
    const MeshBase::element_iterator elem_end = mesh.active_elements_end();

    unsigned int el_num = 0;

    for (; elem_it != elem_end; ++elem_it)
      {
	assert ((*elem_it)->id() < forward_map.size());

	forward_map[(*elem_it)->id()] = el_num++;
      }

    assert (el_num == n_active_elem);
   }

  // build the graph in CSR format.  Note that
  // the edges in the graph will correspond to
  // face neighbors
  {
    std::vector<const Elem*> neighbors_offspring;

    MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
    const MeshBase::element_iterator elem_end = mesh.active_elements_end();

    // This will be exact when there is no refinement and all the
    // elements are of the same type.
    adjncy.reserve (n_active_elem*(*elem_it)->n_neighbors());

    for (; elem_it != elem_end; ++elem_it)
      {
	const Elem* elem = *elem_it;

	assert (elem->id() < forward_map.size());
	assert (forward_map[elem->id()] != libMesh::invalid_uint);

	// maybe there is a better weight?
	// The weight is used to define what a balanced graph is
	vwgt[forward_map[elem->id()]] = elem->n_nodes();

	// The beginning of the adjacency array for this elem
	xadj.push_back(adjncy.size());

	// Loop over the element's neighbors.  An element
	// adjacency corresponds to a face neighbor
	for (unsigned int ms=0; ms<elem->n_neighbors(); ms++)
	  {
	    const Elem* neighbor = elem->neighbor(ms);

	    if (neighbor != NULL)
	      {
		// If the neighbor is active treat it
		// as a connection
		if (neighbor->active())
		  {
		    assert (neighbor->id() < forward_map.size());
		    assert (forward_map[neighbor->id()] != libMesh::invalid_uint);

		    adjncy.push_back (forward_map[neighbor->id()]);
		  }

#ifdef ENABLE_AMR

		// Otherwise we need to find all of the
		// neighbor's children that are connected to
		// us and add them
		else
		  {
		    // The side of the neighbor to which
		    // we are connected
		    const unsigned int ns =
		      neighbor->which_neighbor_am_i (elem);

		    // Get all the active children (& grandchildren, etc...)
		    // of the neighbor.
		    neighbor->active_family_tree (neighbors_offspring);

		    // Get all the neighbor's children that
		    // live on that side and are thus connected
		    // to us
		    for (unsigned int nc=0; nc<neighbors_offspring.size(); nc++)
		      {
			const Elem* child =
			  neighbors_offspring[nc];

			// This does not assume a level-1 mesh.
			// Note that since children have sides numbered
			// coincident with the parent then this is a sufficient test.
			if (child->neighbor(ns) == elem)
			  {
			    assert (child->active());
			    assert (child->id() < forward_map.size());
			    assert (forward_map[child->id()] != libMesh::invalid_uint);

			    adjncy.push_back (forward_map[child->id()]);
			  }
		      }
		  }

#endif /* ifdef ENABLE_AMR */

	      }
	  }
      }

    // The end of the adjacency array for the last elem
    xadj.push_back(adjncy.size());

  } // done building the graph

  // Select which type of partitioning to create

  // Use recursive if the number of partitions is less than or equal to 8
  if (n_pieces <= 8)
    Metis::METIS_PartGraphRecursive(&n, &xadj[0], &adjncy[0], &vwgt[0], NULL,
				    &wgtflag, &numflag, &nparts, &options[0],
				    &edgecut, &part[0]);

  // Otherwise  use kway
  else
    Metis::METIS_PartGraphKway(&n, &xadj[0], &adjncy[0], &vwgt[0], NULL,
			       &wgtflag, &numflag, &nparts, &options[0],
			       &edgecut, &part[0]);

  // Assign the returned processor ids.  The part array contains
  // the processor id for each active element, but in terms of
  // the contiguous indexing we defined above
  {

    MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
    const MeshBase::element_iterator elem_end = mesh.active_elements_end();

    for (; elem_it != elem_end; ++elem_it)
      {
	Elem* elem = *elem_it;

	assert (elem->id() < forward_map.size());
	assert (forward_map[elem->id()] != libMesh::invalid_uint);

	elem->processor_id() =
	  static_cast<short int>(part[forward_map[elem->id()]]);
      }
  }

  STOP_LOG("partition()", "MetisPartitioner");

#endif

}
<commit_msg>fixed for MIPSPro<commit_after>// $Id: metis_partitioner.C,v 1.22 2005-09-30 20:14:12 benkirk Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2005  Benjamin S. Kirk, John W. Peterson

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ Includes   -----------------------------------

// Local Includes -----------------------------------
#include "libmesh_config.h"
#include "mesh_base.h"
#include "metis_partitioner.h"
#include "libmesh_logging.h"
#include "elem.h"

#ifdef HAVE_METIS
// MIPSPro 7.4.2 gets confused about these nested namespaces
# ifdef __sgi
#  include <cstdarg>
# endif
  namespace Metis {
    extern "C" {
#     include "metis.h"
    }
  }
#else
#  include "sfc_partitioner.h"
#endif

// ------------------------------------------------------------
// MetisPartitioner implementation
void MetisPartitioner::_do_partition (MeshBase& mesh,
				      const unsigned int n_pieces)
{
  assert (n_pieces > 0);

  // Check for an easy return
  if (n_pieces == 1)
    {
      this->single_partition (mesh);
      return;
    }

// What to do if the Metis library IS NOT present
#ifndef HAVE_METIS

  here();
  std::cerr << "ERROR: The library has been built without"    << std::endl
	    << "Metis support.  Using a space-filling curve"  << std::endl
	    << "partitioner instead!"                         << std::endl;

  SFCPartitioner sfcp;

  sfcp.partition (mesh, n_pieces);

// What to do if the Metis library IS present
#else

  START_LOG("partition()", "MetisPartitioner");

  const unsigned int n_active_elem = mesh.n_active_elem();
  const unsigned int n_elem        = mesh.n_elem();

  // build the graph
  // the forward_map maps each active element id
  // into a contiguous block of indices for Metis
  std::vector<unsigned int> forward_map (n_elem, libMesh::invalid_uint);

  std::vector<int> xadj;
  std::vector<int> adjncy;
  std::vector<int> options(5);
  std::vector<int> vwgt(n_active_elem);
  std::vector<int> part(n_active_elem);

  xadj.reserve(n_active_elem+1);

  int
    n = static_cast<int>(n_active_elem),  // number of "nodes" (elements)
                                          //   in the graph
    wgtflag = 2,                          // weights on vertices only,
                                          //   none on edges
    numflag = 0,                          // C-style 0-based numbering
    nparts  = static_cast<int>(n_pieces), // number of subdomains to create
    edgecut = 0;                          // the numbers of edges cut by the
                                          //   resulting partition

  // Set the options
  options[0] = 0; // use default options

  // Metis will only consider the active elements.
  // We need to map the active element ids into a
  // contiguous range.
  {

    MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
    const MeshBase::element_iterator elem_end = mesh.active_elements_end();

    unsigned int el_num = 0;

    for (; elem_it != elem_end; ++elem_it)
      {
	assert ((*elem_it)->id() < forward_map.size());

	forward_map[(*elem_it)->id()] = el_num++;
      }

    assert (el_num == n_active_elem);
   }

  // build the graph in CSR format.  Note that
  // the edges in the graph will correspond to
  // face neighbors
  {
    std::vector<const Elem*> neighbors_offspring;

    MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
    const MeshBase::element_iterator elem_end = mesh.active_elements_end();

    // This will be exact when there is no refinement and all the
    // elements are of the same type.
    adjncy.reserve (n_active_elem*(*elem_it)->n_neighbors());

    for (; elem_it != elem_end; ++elem_it)
      {
	const Elem* elem = *elem_it;

	assert (elem->id() < forward_map.size());
	assert (forward_map[elem->id()] != libMesh::invalid_uint);

	// maybe there is a better weight?
	// The weight is used to define what a balanced graph is
	vwgt[forward_map[elem->id()]] = elem->n_nodes();

	// The beginning of the adjacency array for this elem
	xadj.push_back(adjncy.size());

	// Loop over the element's neighbors.  An element
	// adjacency corresponds to a face neighbor
	for (unsigned int ms=0; ms<elem->n_neighbors(); ms++)
	  {
	    const Elem* neighbor = elem->neighbor(ms);

	    if (neighbor != NULL)
	      {
		// If the neighbor is active treat it
		// as a connection
		if (neighbor->active())
		  {
		    assert (neighbor->id() < forward_map.size());
		    assert (forward_map[neighbor->id()] != libMesh::invalid_uint);

		    adjncy.push_back (forward_map[neighbor->id()]);
		  }

#ifdef ENABLE_AMR

		// Otherwise we need to find all of the
		// neighbor's children that are connected to
		// us and add them
		else
		  {
		    // The side of the neighbor to which
		    // we are connected
		    const unsigned int ns =
		      neighbor->which_neighbor_am_i (elem);

		    // Get all the active children (& grandchildren, etc...)
		    // of the neighbor.
		    neighbor->active_family_tree (neighbors_offspring);

		    // Get all the neighbor's children that
		    // live on that side and are thus connected
		    // to us
		    for (unsigned int nc=0; nc<neighbors_offspring.size(); nc++)
		      {
			const Elem* child =
			  neighbors_offspring[nc];

			// This does not assume a level-1 mesh.
			// Note that since children have sides numbered
			// coincident with the parent then this is a sufficient test.
			if (child->neighbor(ns) == elem)
			  {
			    assert (child->active());
			    assert (child->id() < forward_map.size());
			    assert (forward_map[child->id()] != libMesh::invalid_uint);

			    adjncy.push_back (forward_map[child->id()]);
			  }
		      }
		  }

#endif /* ifdef ENABLE_AMR */

	      }
	  }
      }

    // The end of the adjacency array for the last elem
    xadj.push_back(adjncy.size());

  } // done building the graph

  // Select which type of partitioning to create

  // Use recursive if the number of partitions is less than or equal to 8
  if (n_pieces <= 8)
    Metis::METIS_PartGraphRecursive(&n, &xadj[0], &adjncy[0], &vwgt[0], NULL,
				    &wgtflag, &numflag, &nparts, &options[0],
				    &edgecut, &part[0]);

  // Otherwise  use kway
  else
    Metis::METIS_PartGraphKway(&n, &xadj[0], &adjncy[0], &vwgt[0], NULL,
			       &wgtflag, &numflag, &nparts, &options[0],
			       &edgecut, &part[0]);

  // Assign the returned processor ids.  The part array contains
  // the processor id for each active element, but in terms of
  // the contiguous indexing we defined above
  {

    MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
    const MeshBase::element_iterator elem_end = mesh.active_elements_end();

    for (; elem_it != elem_end; ++elem_it)
      {
	Elem* elem = *elem_it;

	assert (elem->id() < forward_map.size());
	assert (forward_map[elem->id()] != libMesh::invalid_uint);

	elem->processor_id() =
	  static_cast<short int>(part[forward_map[elem->id()]]);
      }
  }

  STOP_LOG("partition()", "MetisPartitioner");

#endif

}
<|endoftext|>


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

#include "wifi_stumbler.h"

WifiStumbler::WifiStumbler()
{
}

WifiStumbler::~WifiStumbler()
{
  iw_sockets_close(wlan_sock_);
}

wifi_tools::WifiData WifiStumbler::getData()
{
  return wifi_stumble_;
}

void WifiStumbler::setFrame(std::string frame_id)
{
  wifi_stumble_.header.frame_id = frame_id;
}

bool WifiStumbler::initialize(std::string wlan_if)
{
  wlan_if_ = wlan_if;
  wlan_sock_ = iw_sockets_open();
  if(wlan_sock_<0)
  {
   ROS_ERROR("Failed to open wlan socket on %s", wlan_if_.c_str());
   return false;
  }
  return true;
}

bool WifiStumbler::stumble()
{
  int pid;
  pid = getpid();

  struct iwreq w_request;
  w_request.u.data.pointer = (caddr_t)&pid;
  w_request.u.data.length = 0;

  if (iw_set_ext(wlan_sock_, wlan_if_.c_str(), SIOCSIWSCAN, &w_request) < 0)
  {
    ROS_ERROR("Couldn't start stumbler.");
    return false;
  }

  timeval time;
  time.tv_sec = 0;
  time.tv_usec = 200000;

  uint8_t *p_buff = NULL;
  int buff_size = IW_SCAN_MAX_DATA;

  bool is_end = false;
  while(!is_end)
  {
    fd_set fds;
    int ret;
    FD_ZERO(&fds);
    ret = select(0, &fds, NULL, NULL, &time);
    if (ret == 0)
    {
      uint8_t *p_buff2;
      while (!is_end)
      {
        p_buff2 = (uint8_t *)realloc(p_buff, buff_size);
        p_buff = p_buff2;
        w_request.u.data.pointer = p_buff;
        w_request.u.data.flags = 0;
        w_request.u.data.length = buff_size;
        if (iw_get_ext(wlan_sock_, wlan_if_.c_str(), SIOCGIWSCAN, &w_request) < 0)
        {
          if (errno == E2BIG && range_.we_version_compiled > 16)
          {
            if (w_request.u.data.length > buff_size)
              buff_size = w_request.u.data.length;
            else
              buff_size *= 2;
            continue;
          }
          else if (errno == EAGAIN)
          {
            time.tv_sec = 0;
            time.tv_usec = 200000;
            break;
          }
        }
        else
          is_end = true;
      }
    }
  }

  // Put wifi data into ROS message
  wifi_tools::AccessPoint ap;
  iw_event event;
  stream_descr stream;

  wifi_stumble_.data.clear();
  wifi_stumble_.header.stamp = ros::Time::now();

  iw_init_event_stream(&stream, (char *)p_buff, w_request.u.data.length);
  is_end = false;
  int value = 0;
  while(!is_end)
  {
    value = iw_extract_event_stream(&stream, &event, range_.we_version_compiled);
    if(!(value>0))
    {
      is_end = true;
    }
    else
    {
      if(event.cmd == IWEVQUAL)
      {
        // quality part of statistics
        //ROS_INFO("command=IWEVQUAL");
        if (event.u.qual.level != 0 || (event.u.qual.updated & (IW_QUAL_DBM | IW_QUAL_RCPI)))
        {
          //ap.noise = event.u.qual.noise;
          ap.ss    = event.u.qual.level;
        }
      }
      else if(event.cmd == SIOCGIWAP)
      {
        // get access point MAC addresses
        //ROS_INFO("command=SIOCGIWAP");
        char mac_buff[1024];
        iw_ether_ntop((const struct ether_addr *)&event.u.ap_addr.sa_data,mac_buff);
        ap.mac_address = std::string(mac_buff);
      }
      else if(event.cmd == SIOCGIWESSID)
      {
        // get ESSID
        //ROS_INFO("command=SIOCGIWESSID");
        wifi_stumble_.data.push_back(ap);
      }
      else if(event.cmd == SIOCGIWENCODE)
      {
        // get encoding token & mode
        //ROS_INFO("command=SIOCGIWENCODE");
      }
      else if(event.cmd == SIOCGIWFREQ)
      {
        // get channel/frequency (Hz)
        //ROS_INFO("command=SIOCGIWFREQ");
      }
      else if(event.cmd == SIOCGIWRATE)
      {
        // get default bit rate (bps)
        //ROS_INFO("command=SIOCGIWRATE");
      }
      else if(event.cmd == SIOCGIWMODE)
      {
        // get operation mode
        //ROS_INFO("command=SIOCGIWMODE");

      }
      else if(event.cmd == IWEVCUSTOM)
      {
        // Driver specific ascii string
        //ROS_INFO("command=IWEVCUSTOM");
      }
      else if(event.cmd == IWEVGENIE)
      {
        // Generic IE (WPA, RSN, WMM, ..)
        //ROS_INFO("command=IWEVGENIE");
      }
      else
      {
        // another command
        //ROS_INFO("another command");
      }
    }
  }

  checkDuplication();

  return true;
}

void WifiStumbler::checkDuplication()
{
  //check duplication of MAC
  std::map<std::string,wifi_tools::AccessPoint> ap_map;
  std::map<std::string,wifi_tools::AccessPoint>::iterator it_map;
  std::vector<wifi_tools::AccessPoint>::iterator it;
  std::string mac;

  it = wifi_stumble_.data.begin();
  while( it != wifi_stumble_.data.end() )
  {
    mac = (std::string)(*it).mac_address;
    if( ap_map.find(mac) == ap_map.end())
    {
      // new access point
      ap_map.insert( std::map<std::string,wifi_tools::AccessPoint>::value_type(mac,*it) );
    }
    else
    {
      // duplicate access point
      //TODO FIFO, or something else?
    }
    ++it;
  }

  wifi_stumble_.data.clear();
  it_map = ap_map.begin();
  while( it_map != ap_map.end() )
  {
    wifi_stumble_.data.push_back(it_map->second);
    ++it_map;
  }
}

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

#include "wifi_stumbler.h"

WifiStumbler::WifiStumbler()
{
}

WifiStumbler::~WifiStumbler()
{
  iw_sockets_close(wlan_sock_);
}

wifi_tools::WifiData WifiStumbler::getData()
{
  return wifi_stumble_;
}

void WifiStumbler::setFrame(std::string frame_id)
{
  wifi_stumble_.header.frame_id = frame_id;
}

bool WifiStumbler::initialize(std::string wlan_if)
{
  wlan_if_ = wlan_if;
  wlan_sock_ = iw_sockets_open();
  if(wlan_sock_<0)
  {
   ROS_ERROR("Failed to open wlan socket on %s", wlan_if_.c_str());
   return false;
  }
  return true;
}

bool WifiStumbler::stumble()
{
  int pid;
  pid = getpid();

  struct iwreq w_request;
  w_request.u.data.pointer = (caddr_t)&pid;
  w_request.u.data.length = 0;

  if (iw_set_ext(wlan_sock_, wlan_if_.c_str(), SIOCSIWSCAN, &w_request) < 0)
  {
    ROS_ERROR("Couldn't start stumbler.");
    return false;
  }

  timeval time;
  time.tv_sec = 0;
  time.tv_usec = 200000;

  uint8_t *p_buff = NULL;
  int buff_size = IW_SCAN_MAX_DATA;

  bool is_end = false;
  while(!is_end)
  {
    fd_set fds;
    int ret;
    FD_ZERO(&fds);
    ret = select(0, &fds, NULL, NULL, &time);
    if (ret == 0)
    {
      uint8_t *p_buff2;
      while (!is_end)
      {
        p_buff2 = (uint8_t *)realloc(p_buff, buff_size);
        p_buff = p_buff2;
        w_request.u.data.pointer = p_buff;
        w_request.u.data.flags = 0;
        w_request.u.data.length = buff_size;
        if (iw_get_ext(wlan_sock_, wlan_if_.c_str(), SIOCGIWSCAN, &w_request) < 0)
        {
          if (errno == E2BIG && range_.we_version_compiled > 16)
          {
            if (w_request.u.data.length > buff_size)
              buff_size = w_request.u.data.length;
            else
              buff_size *= 2;
            continue;
          }
          else if (errno == EAGAIN)
          {
            time.tv_sec = 0;
            time.tv_usec = 200000;
            break;
          }
        }
        else
          is_end = true;
      }
    }
  }

  // Put wifi data into ROS message
  wifi_tools::AccessPoint ap;
  iw_event event;
  stream_descr stream;

  wifi_stumble_.data.clear();
  wifi_stumble_.header.stamp = ros::Time::now();

  iw_init_event_stream(&stream, (char *)p_buff, w_request.u.data.length);
  is_end = false;
  int value = 0;
  while(!is_end)
  {
    value = iw_extract_event_stream(&stream, &event, range_.we_version_compiled);
    if(!(value>0))
    {
      is_end = true;
    }
    else
    {
      if(event.cmd == IWEVQUAL)
      {
        // quality part of statistics
        //ROS_INFO("command=IWEVQUAL");
        if (event.u.qual.level != 0 || (event.u.qual.updated & (IW_QUAL_DBM | IW_QUAL_RCPI)))
        {
          ap.noise = event.u.qual.noise;
          ap.ss    = event.u.qual.level;
        }
      }
      else if(event.cmd == SIOCGIWAP)
      {
        // get access point MAC addresses
        //ROS_INFO("command=SIOCGIWAP");
        char mac_buff[1024];
        iw_ether_ntop((const struct ether_addr *)&event.u.ap_addr.sa_data,mac_buff);
        ap.mac_address = std::string(mac_buff);
      }
      else if(event.cmd == SIOCGIWESSID)
      {
        // get ESSID
        //ROS_INFO("command=SIOCGIWESSID");
        wifi_stumble_.data.push_back(ap);
      }
      else if(event.cmd == SIOCGIWENCODE)
      {
        // get encoding token & mode
        //ROS_INFO("command=SIOCGIWENCODE");
      }
      else if(event.cmd == SIOCGIWFREQ)
      {
        // get channel/frequency (Hz)
        //ROS_INFO("command=SIOCGIWFREQ");
      }
      else if(event.cmd == SIOCGIWRATE)
      {
        // get default bit rate (bps)
        //ROS_INFO("command=SIOCGIWRATE");
      }
      else if(event.cmd == SIOCGIWMODE)
      {
        // get operation mode
        //ROS_INFO("command=SIOCGIWMODE");

      }
      else if(event.cmd == IWEVCUSTOM)
      {
        // Driver specific ascii string
        //ROS_INFO("command=IWEVCUSTOM");
      }
      else if(event.cmd == IWEVGENIE)
      {
        // Generic IE (WPA, RSN, WMM, ..)
        //ROS_INFO("command=IWEVGENIE");
      }
      else
      {
        // another command
        //ROS_INFO("another command");
      }
    }
  }

  checkDuplication();

  return true;
}

void WifiStumbler::checkDuplication()
{
  //check duplication of MAC
  std::map<std::string,wifi_tools::AccessPoint> ap_map;
  std::map<std::string,wifi_tools::AccessPoint>::iterator it_map;
  std::vector<wifi_tools::AccessPoint>::iterator it;
  std::string mac;

  it = wifi_stumble_.data.begin();
  while( it != wifi_stumble_.data.end() )
  {
    mac = (std::string)(*it).mac_address;
    if( ap_map.find(mac) == ap_map.end())
    {
      // new access point
      ap_map.insert( std::map<std::string,wifi_tools::AccessPoint>::value_type(mac,*it) );
    }
    else
    {
      // duplicate access point
      //TODO FIFO, or something else?
    }
    ++it;
  }

  wifi_stumble_.data.clear();
  it_map = ap_map.begin();
  while( it_map != ap_map.end() )
  {
    wifi_stumble_.data.push_back(it_map->second);
    ++it_map;
  }
}

<|endoftext|>


<commit_before>/*
 * Shared memory for sharing data between worker processes.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "shm.hxx"
#include "lock.h"
#include "util/RefCount.hxx"

#include <inline/poison.h>
#include <inline/list.h>
#include <daemon/log.h>

#include <assert.h>
#include <stdint.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>

struct page {
    struct list_head siblings;

    unsigned num_pages;
    uint8_t *data;
};

struct shm {
    RefCount ref;

    size_t page_size;
    unsigned num_pages;

    /** this lock protects the linked list */
    struct lock lock;

    struct list_head available;
    struct page pages[1];
};

static inline unsigned
calc_header_pages(size_t page_size, unsigned num_pages)
{
    size_t header_size = sizeof(struct shm) +
        (num_pages - 1) * sizeof(struct page);
    return (header_size + page_size - 1) / page_size;
}

gcc_const
static uint8_t *
shm_at(struct shm *shm, size_t offset)
{
    return (uint8_t *)shm + offset;
}

static uint8_t *
shm_data(struct shm *shm)
{
    unsigned header_pages = calc_header_pages(shm->page_size, shm->num_pages);

    return shm_at(shm, shm->page_size * header_pages);
}

struct shm *
shm_new(size_t page_size, unsigned num_pages)
{
    assert(page_size >= sizeof(size_t));
    assert(num_pages > 0);

    const unsigned header_pages = calc_header_pages(page_size, num_pages);
    void *p = mmap(nullptr, page_size * (header_pages + num_pages),
                   PROT_READ|PROT_WRITE,
                   MAP_ANONYMOUS|MAP_SHARED,
                   -1, 0);
    if (p == (void *)-1)
        return nullptr;

    struct shm *shm = (struct shm *)p;
    shm->ref.Init();
    shm->page_size = page_size;
    shm->num_pages = num_pages;

    lock_init(&shm->lock);

    list_init(&shm->available);
    list_add(&shm->pages[0].siblings, &shm->available);
    shm->pages[0].num_pages = num_pages;
    shm->pages[0].data = shm_data(shm);

#if 0
    /* disabled because this causes page faults and immediately
       allocates physical memory for the areas that aren't used yet */
    poison_noaccess(shm_data(shm), page_size * num_pages);
#endif

    return shm;
}

void
shm_ref(struct shm *shm)
{
    assert(shm != nullptr);

    shm->ref.Get();
}

void
shm_close(struct shm *shm)
{
    unsigned header_pages;
    int ret;

    assert(shm != nullptr);

    if (shm->ref.Put())
        lock_destroy(&shm->lock);

    header_pages = calc_header_pages(shm->page_size, shm->num_pages);
    ret = munmap(shm, shm->page_size * (header_pages + shm->num_pages));
    if (ret < 0)
        daemon_log(1, "munmap() failed: %s\n", strerror(errno));
}

size_t
shm_page_size(const struct shm *shm)
{
    return shm->page_size;
}

static struct page *
shm_find_available(struct shm *shm, unsigned num_pages)
{
    for (struct page *page = (struct page *)shm->available.next;
         &page->siblings != &shm->available;
         page = (struct page *)page->siblings.next)
        if (page->num_pages >= num_pages)
            return page;

    return nullptr;
}

static struct page *
shm_split_page(const struct shm *shm, struct page *page, unsigned num_pages)
{
    assert(page->num_pages > num_pages);

    page->num_pages -= num_pages;

    page[page->num_pages].data = page->data + shm->page_size * page->num_pages;
    page += page->num_pages;
    page->num_pages = num_pages;

    return page;
}

void *
shm_alloc(struct shm *shm, unsigned num_pages)
{
    assert(num_pages > 0);

    lock_lock(&shm->lock);

    struct page *page = shm_find_available(shm, num_pages);
    if (page == nullptr) {
        lock_unlock(&shm->lock);
        return nullptr;
    }

    assert(page->num_pages >= num_pages);

    if (page->num_pages == num_pages) {
        list_remove(&page->siblings);
        lock_unlock(&shm->lock);

        poison_undefined(page->data, shm->page_size * num_pages);
        return page->data;
    } else {
        page = shm_split_page(shm, page, num_pages);

        lock_unlock(&shm->lock);

        poison_undefined(page->data, shm->page_size * num_pages);
        return page->data;
    }
}

static unsigned
shm_page_number(struct shm *shm, const void *p)
{
    ptrdiff_t difference = (const uint8_t *)p - shm_data(shm);
    unsigned page_number = difference / shm->page_size;
    assert(difference % shm->page_size == 0);

    assert(page_number < shm->num_pages);

    return page_number;
}

/** merge this page with its adjacent pages if possible, to create
    bigger "available" areas */
static void
shm_merge(struct shm *shm, struct page *page)
{
    unsigned page_number = shm_page_number(shm, page->data);

    /* merge with previous page? */

    struct page *other = (struct page *)page->siblings.prev;
    if (&other->siblings != &shm->available &&
        shm_page_number(shm, other->data) + other->num_pages == page_number) {
        other->num_pages += page->num_pages;
        list_remove(&page->siblings);
        page = other;
    }

    /* merge with next page? */

    other = (struct page *)page->siblings.next;
    if (&other->siblings != &shm->available &&
        page_number + page->num_pages == shm_page_number(shm, other->data)) {
        page->num_pages += other->num_pages;
        list_remove(&other->siblings);
    }
}

void
shm_free(struct shm *shm, const void *p)
{
    unsigned page_number = shm_page_number(shm, p);
    struct page *page = &shm->pages[page_number];
    struct page *prev;

    poison_noaccess(page->data, shm->page_size * page->num_pages);

    lock_lock(&shm->lock);

    for (prev = (struct page *)&shm->available;
         prev->siblings.next != &shm->available;
         prev = (struct page *)prev->siblings.next) {
    }

    list_add(&page->siblings, &prev->siblings);

    shm_merge(shm, page);

    lock_unlock(&shm->lock);
}
<commit_msg>shm: add assertions on page order<commit_after>/*
 * Shared memory for sharing data between worker processes.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "shm.hxx"
#include "lock.h"
#include "util/RefCount.hxx"

#include <inline/poison.h>
#include <inline/list.h>
#include <daemon/log.h>

#include <assert.h>
#include <stdint.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>

struct page {
    struct list_head siblings;

    unsigned num_pages;
    uint8_t *data;
};

struct shm {
    RefCount ref;

    size_t page_size;
    unsigned num_pages;

    /** this lock protects the linked list */
    struct lock lock;

    struct list_head available;
    struct page pages[1];
};

static inline unsigned
calc_header_pages(size_t page_size, unsigned num_pages)
{
    size_t header_size = sizeof(struct shm) +
        (num_pages - 1) * sizeof(struct page);
    return (header_size + page_size - 1) / page_size;
}

gcc_const
static uint8_t *
shm_at(struct shm *shm, size_t offset)
{
    return (uint8_t *)shm + offset;
}

static uint8_t *
shm_data(struct shm *shm)
{
    unsigned header_pages = calc_header_pages(shm->page_size, shm->num_pages);

    return shm_at(shm, shm->page_size * header_pages);
}

struct shm *
shm_new(size_t page_size, unsigned num_pages)
{
    assert(page_size >= sizeof(size_t));
    assert(num_pages > 0);

    const unsigned header_pages = calc_header_pages(page_size, num_pages);
    void *p = mmap(nullptr, page_size * (header_pages + num_pages),
                   PROT_READ|PROT_WRITE,
                   MAP_ANONYMOUS|MAP_SHARED,
                   -1, 0);
    if (p == (void *)-1)
        return nullptr;

    struct shm *shm = (struct shm *)p;
    shm->ref.Init();
    shm->page_size = page_size;
    shm->num_pages = num_pages;

    lock_init(&shm->lock);

    list_init(&shm->available);
    list_add(&shm->pages[0].siblings, &shm->available);
    shm->pages[0].num_pages = num_pages;
    shm->pages[0].data = shm_data(shm);

#if 0
    /* disabled because this causes page faults and immediately
       allocates physical memory for the areas that aren't used yet */
    poison_noaccess(shm_data(shm), page_size * num_pages);
#endif

    return shm;
}

void
shm_ref(struct shm *shm)
{
    assert(shm != nullptr);

    shm->ref.Get();
}

void
shm_close(struct shm *shm)
{
    unsigned header_pages;
    int ret;

    assert(shm != nullptr);

    if (shm->ref.Put())
        lock_destroy(&shm->lock);

    header_pages = calc_header_pages(shm->page_size, shm->num_pages);
    ret = munmap(shm, shm->page_size * (header_pages + shm->num_pages));
    if (ret < 0)
        daemon_log(1, "munmap() failed: %s\n", strerror(errno));
}

size_t
shm_page_size(const struct shm *shm)
{
    return shm->page_size;
}

static struct page *
shm_find_available(struct shm *shm, unsigned num_pages)
{
    for (struct page *page = (struct page *)shm->available.next;
         &page->siblings != &shm->available;
         page = (struct page *)page->siblings.next)
        if (page->num_pages >= num_pages)
            return page;

    return nullptr;
}

static struct page *
shm_split_page(const struct shm *shm, struct page *page, unsigned num_pages)
{
    assert(page->num_pages > num_pages);

    page->num_pages -= num_pages;

    page[page->num_pages].data = page->data + shm->page_size * page->num_pages;
    page += page->num_pages;
    page->num_pages = num_pages;

    return page;
}

void *
shm_alloc(struct shm *shm, unsigned num_pages)
{
    assert(num_pages > 0);

    lock_lock(&shm->lock);

    struct page *page = shm_find_available(shm, num_pages);
    if (page == nullptr) {
        lock_unlock(&shm->lock);
        return nullptr;
    }

    assert(page->siblings.prev == &shm->available ||
           page->siblings.prev < &page->siblings);
    assert(page->siblings.next == &shm->available ||
           page->siblings.next > &page->siblings);

    assert(page->num_pages >= num_pages);

    if (page->num_pages == num_pages) {
        list_remove(&page->siblings);
        lock_unlock(&shm->lock);

        poison_undefined(page->data, shm->page_size * num_pages);
        return page->data;
    } else {
        page = shm_split_page(shm, page, num_pages);

        lock_unlock(&shm->lock);

        poison_undefined(page->data, shm->page_size * num_pages);
        return page->data;
    }
}

static unsigned
shm_page_number(struct shm *shm, const void *p)
{
    ptrdiff_t difference = (const uint8_t *)p - shm_data(shm);
    unsigned page_number = difference / shm->page_size;
    assert(difference % shm->page_size == 0);

    assert(page_number < shm->num_pages);

    return page_number;
}

/** merge this page with its adjacent pages if possible, to create
    bigger "available" areas */
static void
shm_merge(struct shm *shm, struct page *page)
{
    unsigned page_number = shm_page_number(shm, page->data);

    /* merge with previous page? */

    assert(page->siblings.prev == &shm->available ||
           page->siblings.prev < &page->siblings);

    struct page *other = (struct page *)page->siblings.prev;
    if (&other->siblings != &shm->available &&
        shm_page_number(shm, other->data) + other->num_pages == page_number) {
        other->num_pages += page->num_pages;
        list_remove(&page->siblings);
        page = other;
    }

    /* merge with next page? */

    assert(page->siblings.next == &shm->available ||
           page->siblings.next > &page->siblings);

    other = (struct page *)page->siblings.next;
    if (&other->siblings != &shm->available &&
        page_number + page->num_pages == shm_page_number(shm, other->data)) {
        page->num_pages += other->num_pages;
        list_remove(&other->siblings);
    }
}

void
shm_free(struct shm *shm, const void *p)
{
    unsigned page_number = shm_page_number(shm, p);
    struct page *page = &shm->pages[page_number];
    struct page *prev;

    poison_noaccess(page->data, shm->page_size * page->num_pages);

    lock_lock(&shm->lock);

    for (prev = (struct page *)&shm->available;
         prev->siblings.next != &shm->available;
         prev = (struct page *)prev->siblings.next) {
    }

    list_add(&page->siblings, &prev->siblings);

    shm_merge(shm, page);

    lock_unlock(&shm->lock);
}
<|endoftext|>


<commit_before>#include <GL/glew.h>
#include "windowManager.h"
#include "Updatable.h"
#include "Renderable.h"
#include "collisionable.h"
#include "postProcessManager.h"
#include "input.h"

WindowManager::WindowManager(int virtualWidth, int virtualHeight, bool fullscreen, RenderChain* renderChain, int fsaa)
: virtualSize(virtualWidth, virtualHeight), renderChain(renderChain), fullscreen(fullscreen), fsaa(fsaa)
{
    srand(time(NULL));
    windowHasFocus = true;
    min_aspect_ratio = float(virtualWidth) / float(virtualHeight);
    allow_virtual_resize = false;

    create();
    glewInit();
}

WindowManager::~WindowManager()
{
}

void WindowManager::render()
{
    // Clear the window
    window.clear(sf::Color(20, 20, 20));

    //Call the first item of the rendering chain.
    renderChain->render(window);

    // Display things on screen
    window.display();
}

void WindowManager::close()
{
    window.close();
}

void WindowManager::setFullscreen(bool new_fullscreen)
{
    if (fullscreen == new_fullscreen)
        return;
    fullscreen = new_fullscreen;
    create();
}
void WindowManager::setFSAA(int new_fsaa)
{
    if (fsaa == new_fsaa)
        return;
    fsaa = new_fsaa;
    create();
}

sf::Vector2f WindowManager::mapPixelToCoords(const sf::Vector2i& point) const
{
    return window.mapPixelToCoords(point);
}

sf::Vector2i WindowManager::mapCoordsToPixel(const sf::Vector2f& point) const
{
    return window.mapCoordsToPixel(point);
}

void WindowManager::create()
{
    // Create the window of the application
    int windowWidth = virtualSize.x;
    int windowHeight = virtualSize.y;

    sf::VideoMode desktop = sf::VideoMode::getDesktopMode();
    if (fullscreen)
    {
        windowWidth = desktop.width;
        windowHeight = desktop.height;
    }else{
        unsigned int scale = 2;
        while(windowWidth * scale < desktop.width && windowHeight * scale < desktop.height)
            scale += 1;
        windowWidth *= scale - 1;
        windowHeight *= scale - 1;

        while(windowWidth >= int(desktop.width) || windowHeight >= int(desktop.height) - 100)
        {
            windowWidth *= 0.9;
            windowHeight *= 0.9;
        }
    }

    sf::ContextSettings context_settings(24, 8, fsaa, 2, 0);
    if (fullscreen)
        window.create(sf::VideoMode(windowWidth, windowHeight, 32), WINDOW_TITLE, sf::Style::Fullscreen, context_settings);
    else
        window.create(sf::VideoMode(windowWidth, windowHeight, 32), WINDOW_TITLE, sf::Style::Default, context_settings);
    sf::ContextSettings settings = window.getSettings();
    LOG(INFO) << "OpenGL version: " << settings.majorVersion << "." << settings.minorVersion;
    window.setVerticalSyncEnabled(false);
    window.setFramerateLimit(60);
    window.setMouseCursorVisible(false);
    setupView();
}

void WindowManager::setupView()
{
    sf::Vector2f window_size = sf::Vector2f(window.getSize());
    if (window_size.x / window_size.y > min_aspect_ratio)
    {
        if (allow_virtual_resize)
            virtualSize.x = virtualSize.y * (window_size.x / window_size.y);

        float aspect = window_size.y * float(virtualSize.x) / float(virtualSize.y) / window_size.x;
        float offset = 0;//0.5 - 0.5 * aspect;
        sf::View view(sf::Vector2f(virtualSize.x/2,virtualSize.y/2), sf::Vector2f(virtualSize.x, virtualSize.y));
        view.setViewport(sf::FloatRect(offset, 0, aspect, 1));
        window.setView(view);
    }else{
        virtualSize.x = virtualSize.y * min_aspect_ratio;

        float aspect = window_size.x / window_size.y * float(virtualSize.y) / float(virtualSize.x);
        float offset = 0.5 - 0.5 * aspect;
        sf::View view(sf::Vector2f(virtualSize.x/2,virtualSize.y/2), sf::Vector2f(virtualSize.x, virtualSize.y));
        view.setViewport(sf::FloatRect(0, offset, 1, aspect));
        window.setView(view);
    }
}
<commit_msg>Use alt+enter to switch between windowed and full screen.<commit_after>#include <GL/glew.h>
#include "windowManager.h"
#include "Updatable.h"
#include "Renderable.h"
#include "collisionable.h"
#include "postProcessManager.h"
#include "input.h"

WindowManager::WindowManager(int virtualWidth, int virtualHeight, bool fullscreen, RenderChain* renderChain, int fsaa)
: virtualSize(virtualWidth, virtualHeight), renderChain(renderChain), fullscreen(fullscreen), fsaa(fsaa)
{
    srand(time(NULL));
    windowHasFocus = true;
    min_aspect_ratio = float(virtualWidth) / float(virtualHeight);
    allow_virtual_resize = false;

    create();
    glewInit();
}

WindowManager::~WindowManager()
{
}

void WindowManager::render()
{
    if (InputHandler::keyboardIsPressed(sf::Keyboard::Enter) && (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt) || sf::Keyboard::isKeyPressed(sf::Keyboard::RAlt)))
    {
        setFullscreen(!isFullscreen());
    }

    // Clear the window
    window.clear(sf::Color(20, 20, 20));

    //Call the first item of the rendering chain.
    renderChain->render(window);

    // Display things on screen
    window.display();
}

void WindowManager::close()
{
    window.close();
}

void WindowManager::setFullscreen(bool new_fullscreen)
{
    if (fullscreen == new_fullscreen)
        return;
    fullscreen = new_fullscreen;
    create();
}
void WindowManager::setFSAA(int new_fsaa)
{
    if (fsaa == new_fsaa)
        return;
    fsaa = new_fsaa;
    create();
}

sf::Vector2f WindowManager::mapPixelToCoords(const sf::Vector2i& point) const
{
    return window.mapPixelToCoords(point);
}

sf::Vector2i WindowManager::mapCoordsToPixel(const sf::Vector2f& point) const
{
    return window.mapCoordsToPixel(point);
}

void WindowManager::create()
{
    // Create the window of the application
    int windowWidth = virtualSize.x;
    int windowHeight = virtualSize.y;

    sf::VideoMode desktop = sf::VideoMode::getDesktopMode();
    if (fullscreen)
    {
        windowWidth = desktop.width;
        windowHeight = desktop.height;
    }else{
        unsigned int scale = 2;
        while(windowWidth * scale < desktop.width && windowHeight * scale < desktop.height)
            scale += 1;
        windowWidth *= scale - 1;
        windowHeight *= scale - 1;

        while(windowWidth >= int(desktop.width) || windowHeight >= int(desktop.height) - 100)
        {
            windowWidth *= 0.9;
            windowHeight *= 0.9;
        }
    }

    sf::ContextSettings context_settings(24, 8, fsaa, 2, 0);
    if (fullscreen)
        window.create(sf::VideoMode(windowWidth, windowHeight, 32), WINDOW_TITLE, sf::Style::Fullscreen, context_settings);
    else
        window.create(sf::VideoMode(windowWidth, windowHeight, 32), WINDOW_TITLE, sf::Style::Default, context_settings);
    sf::ContextSettings settings = window.getSettings();
    LOG(INFO) << "OpenGL version: " << settings.majorVersion << "." << settings.minorVersion;
    window.setVerticalSyncEnabled(false);
    window.setFramerateLimit(60);
    window.setMouseCursorVisible(false);
    setupView();
}

void WindowManager::setupView()
{
    sf::Vector2f window_size = sf::Vector2f(window.getSize());
    if (window_size.x / window_size.y > min_aspect_ratio)
    {
        if (allow_virtual_resize)
            virtualSize.x = virtualSize.y * (window_size.x / window_size.y);

        float aspect = window_size.y * float(virtualSize.x) / float(virtualSize.y) / window_size.x;
        float offset = 0;//0.5 - 0.5 * aspect;
        sf::View view(sf::Vector2f(virtualSize.x/2,virtualSize.y/2), sf::Vector2f(virtualSize.x, virtualSize.y));
        view.setViewport(sf::FloatRect(offset, 0, aspect, 1));
        window.setView(view);
    }else{
        virtualSize.x = virtualSize.y * min_aspect_ratio;

        float aspect = window_size.x / window_size.y * float(virtualSize.y) / float(virtualSize.x);
        float offset = 0.5 - 0.5 * aspect;
        sf::View view(sf::Vector2f(virtualSize.x/2,virtualSize.y/2), sf::Vector2f(virtualSize.x, virtualSize.y));
        view.setViewport(sf::FloatRect(0, offset, 1, aspect));
        window.setView(view);
    }
}
<|endoftext|>


<commit_before>#include <cstddef>
#include <cstdio>
#include <csignal>
#include <unistd.h>
#include <cstring>
#include <string>
#include <iostream>

#include <sys/reboot.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "cpbuffer.h"
#include "control-cmds.h"
#include "service-constants.h"

// shutdown:  shut down the system
// This utility communicates with the dinit daemon via a unix socket (/dev/initctl).

void do_system_shutdown(ShutdownType shutdown_type);
static void unmount_disks();
static void swap_off();
static void wait_for_reply(CPBuffer<1024> &rbuffer, int fd);

class ReadCPException
{
    public:
    int errcode;
    ReadCPException(int err) : errcode(err) { }
};

int main(int argc, char **argv)
{
    using namespace std;

    bool show_help = false;
    bool sys_shutdown = false;
    bool use_passed_cfd = false;

    auto shutdown_type = ShutdownType::POWEROFF;

    for (int i = 1; i < argc; i++) {
        if (argv[i][0] == '-') {
            if (strcmp(argv[i], "--help") == 0) {
                show_help = true;
                break;
            }

            if (strcmp(argv[i], "--system") == 0) {
                sys_shutdown = true;
            }
            else if (strcmp(argv[i], "-r") == 0) {
                shutdown_type = ShutdownType::REBOOT;
            }
            else if (strcmp(argv[i], "-h") == 0) {
                shutdown_type = ShutdownType::HALT;
            }
            else if (strcmp(argv[i], "-p") == 0) {
                shutdown_type = ShutdownType::POWEROFF;
            }
            else if (strcmp(argv[i], "--use-passed-cfd") == 0) {
                use_passed_cfd = true;
            }
            else {
                cerr << "Unrecognized command-line parameter: " << argv[i] << endl;
                return 1;
            }
        }
        else {
            // time argument? TODO
            show_help = true;
        }
    }

    if (show_help) {
        cout << "dinit-shutdown :   shutdown the system" << endl;
        cout << "  --help           : show this help" << endl;
        cout << "  -r               : reboot" << endl;
        cout << "  -h               : halt system" << endl;
        cout << "  -p               : power down (default)" << endl;
        cout << "  --use-passed-cfd : use the socket file descriptor identified by the DINIT_CS_FD" << endl;
        cout << "                     environment variable to communicate with the init daemon." << endl;
        cout << "  --system         : perform shutdown immediately, instead of issuing shutdown" << endl;
        cout << "                     command to the init program. Not recommended for use" << endl;
        cout << "                     by users." << endl;
        return 1;
    }

    if (sys_shutdown) {
        do_system_shutdown(shutdown_type);
        return 0;
    }

    signal(SIGPIPE, SIG_IGN);

    int socknum = 0;

    if (use_passed_cfd) {
        char * dinit_cs_fd_env = getenv("DINIT_CS_FD");
        if (dinit_cs_fd_env != nullptr) {
            char * endptr;
            long int cfdnum = strtol(dinit_cs_fd_env, &endptr, 10);
            if (endptr != dinit_cs_fd_env) {
                socknum = (int) cfdnum;
            }
            else {
                use_passed_cfd = false;
            }
        }
        else {
            use_passed_cfd = false;
        }
    }

    if (! use_passed_cfd) {
        socknum = socket(AF_UNIX, SOCK_STREAM, 0);
        if (socknum == -1) {
            perror("socket");
            return 1;
        }

        const char *naddr = "/dev/dinitctl";

        struct sockaddr_un name;
        name.sun_family = AF_UNIX;
        strcpy(name.sun_path, naddr);
        int sunlen = offsetof(struct sockaddr_un, sun_path) + strlen(naddr) + 1; // family, (string), nul

        int connr = connect(socknum, (struct sockaddr *) &name, sunlen);
        if (connr == -1) {
            perror("connect");
            return 1;
        }
    }

    // Build buffer;
    //uint16_t sname_len = strlen(service_name);
    int bufsize = 2;
    char * buf = new char[bufsize];

    buf[0] = DINIT_CP_SHUTDOWN;
    buf[1] = static_cast<char>(shutdown_type);

    cout << "Issuing shutdown command..." << endl;

    // TODO make sure to write the whole buffer
    int r = write(socknum, buf, bufsize);
    if (r == -1) {
        perror("write");
        return 1;
    }

    // Wait for ACK/NACK
    // r = read(socknum, buf, 1);
    //if (r > 0) {
    //    cout << "Received acknowledgement. System should now shut down." << endl;
    //}

    CPBuffer<1024> rbuffer;
    try {
        wait_for_reply(rbuffer, socknum);

        if (rbuffer[0] != DINIT_RP_ACK) {
            cerr << "shutdown: control socket protocol error" << endl;
            return 1;
        }
    }
    catch (ReadCPException &exc)
    {
        cerr << "shutdown: control socket read failure or protocol error" << endl;
        return 1;
    }

    while (true) {
        pause();
    }

    return 0;
}

// Fill a circular buffer from a file descriptor, reading at least _rlength_ bytes.
// Throws ReadException if the requested number of bytes cannot be read, with:
//     errcode = 0   if end of stream (remote end closed)
//     errcode = errno   if another error occurred
// Note that EINTR is ignored (i.e. the read will be re-tried).
static void fillBufferTo(CPBuffer<1024> *buf, int fd, int rlength)
{
    do {
        int r = buf->fill_to(fd, rlength);
        if (r == -1) {
            if (errno != EINTR) {
                throw ReadCPException(errno);
            }
        }
        else if (r == 0) {
            throw ReadCPException(0);
        }
        else {
            return;
        }
    }
    while (true);
}

// Wait for a reply packet, skipping over any information packets
// that are received in the meantime.
static void wait_for_reply(CPBuffer<1024> &rbuffer, int fd)
{
    fillBufferTo(&rbuffer, fd, 1);

    while (rbuffer[0] >= 100) {
        // Information packet; discard.
        fillBufferTo(&rbuffer, fd, 1);
        int pktlen = (unsigned char) rbuffer[1];

        rbuffer.consume(1);  // Consume one byte so we'll read one byte of the next packet
        fillBufferTo(&rbuffer, fd, pktlen);
        rbuffer.consume(pktlen - 1);
    }
}

// Actually shut down the system.
void do_system_shutdown(ShutdownType shutdown_type)
{
    using namespace std;

    // Mask all signals to prevent death of our parent etc from terminating us
    sigset_t allsigs;
    sigfillset(&allsigs);
    sigprocmask(SIG_SETMASK, &allsigs, nullptr);

    int reboot_type = 0;
    if (shutdown_type == ShutdownType::REBOOT) reboot_type = RB_AUTOBOOT;
    else if (shutdown_type == ShutdownType::POWEROFF) reboot_type = RB_POWER_OFF;
    else reboot_type = RB_HALT_SYSTEM;

    // Write to console rather than any terminal, since we lose the terminal it seems:
    close(STDOUT_FILENO);
    int consfd = open("/dev/console", O_WRONLY);
    if (consfd != STDOUT_FILENO) {
        dup2(consfd, STDOUT_FILENO);
    }

    cout << "Sending TERM/KILL to all processes..." << endl; // DAV

    // Send TERM/KILL to all (remaining) processes
    kill(-1, SIGTERM);
    sleep(1);
    kill(-1, SIGKILL);

    // perform shutdown
    cout << "Turning off swap..." << endl;
    swap_off();
    cout << "Unmounting disks..." << endl;
    unmount_disks();
    sync();

    cout << "Issuing shutdown via kernel..." << endl;
    reboot(reboot_type);
}

static void unmount_disks()
{
    pid_t chpid = fork();
    if (chpid == 0) {
        // umount -a -r
        //  -a : all filesystems (except proc)
        //  -r : mount readonly if can't unmount
        execl("/bin/umount", "/bin/umount", "-a", "-r", nullptr);
    }
    else if (chpid > 0) {
        int status;
        waitpid(chpid, &status, 0);
    }
}

static void swap_off()
{
    pid_t chpid = fork();
    if (chpid == 0) {
        // swapoff -a
        execl("/sbin/swapoff", "/sbin/swapoff", "-a", nullptr);
    }
    else if (chpid > 0) {
        int status;
        waitpid(chpid, &status, 0);
    }
}
<commit_msg>Fix trivial memory leak.<commit_after>#include <cstddef>
#include <cstdio>
#include <csignal>
#include <unistd.h>
#include <cstring>
#include <string>
#include <iostream>

#include <sys/reboot.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "cpbuffer.h"
#include "control-cmds.h"
#include "service-constants.h"

// shutdown:  shut down the system
// This utility communicates with the dinit daemon via a unix socket (/dev/initctl).

void do_system_shutdown(ShutdownType shutdown_type);
static void unmount_disks();
static void swap_off();
static void wait_for_reply(CPBuffer<1024> &rbuffer, int fd);

class ReadCPException
{
    public:
    int errcode;
    ReadCPException(int err) : errcode(err) { }
};

int main(int argc, char **argv)
{
    using namespace std;

    bool show_help = false;
    bool sys_shutdown = false;
    bool use_passed_cfd = false;

    auto shutdown_type = ShutdownType::POWEROFF;

    for (int i = 1; i < argc; i++) {
        if (argv[i][0] == '-') {
            if (strcmp(argv[i], "--help") == 0) {
                show_help = true;
                break;
            }

            if (strcmp(argv[i], "--system") == 0) {
                sys_shutdown = true;
            }
            else if (strcmp(argv[i], "-r") == 0) {
                shutdown_type = ShutdownType::REBOOT;
            }
            else if (strcmp(argv[i], "-h") == 0) {
                shutdown_type = ShutdownType::HALT;
            }
            else if (strcmp(argv[i], "-p") == 0) {
                shutdown_type = ShutdownType::POWEROFF;
            }
            else if (strcmp(argv[i], "--use-passed-cfd") == 0) {
                use_passed_cfd = true;
            }
            else {
                cerr << "Unrecognized command-line parameter: " << argv[i] << endl;
                return 1;
            }
        }
        else {
            // time argument? TODO
            show_help = true;
        }
    }

    if (show_help) {
        cout << "dinit-shutdown :   shutdown the system" << endl;
        cout << "  --help           : show this help" << endl;
        cout << "  -r               : reboot" << endl;
        cout << "  -h               : halt system" << endl;
        cout << "  -p               : power down (default)" << endl;
        cout << "  --use-passed-cfd : use the socket file descriptor identified by the DINIT_CS_FD" << endl;
        cout << "                     environment variable to communicate with the init daemon." << endl;
        cout << "  --system         : perform shutdown immediately, instead of issuing shutdown" << endl;
        cout << "                     command to the init program. Not recommended for use" << endl;
        cout << "                     by users." << endl;
        return 1;
    }

    if (sys_shutdown) {
        do_system_shutdown(shutdown_type);
        return 0;
    }

    signal(SIGPIPE, SIG_IGN);

    int socknum = 0;

    if (use_passed_cfd) {
        char * dinit_cs_fd_env = getenv("DINIT_CS_FD");
        if (dinit_cs_fd_env != nullptr) {
            char * endptr;
            long int cfdnum = strtol(dinit_cs_fd_env, &endptr, 10);
            if (endptr != dinit_cs_fd_env) {
                socknum = (int) cfdnum;
            }
            else {
                use_passed_cfd = false;
            }
        }
        else {
            use_passed_cfd = false;
        }
    }

    if (! use_passed_cfd) {
        socknum = socket(AF_UNIX, SOCK_STREAM, 0);
        if (socknum == -1) {
            perror("socket");
            return 1;
        }

        const char *naddr = "/dev/dinitctl";

        struct sockaddr_un name;
        name.sun_family = AF_UNIX;
        strcpy(name.sun_path, naddr);
        int sunlen = offsetof(struct sockaddr_un, sun_path) + strlen(naddr) + 1; // family, (string), nul

        int connr = connect(socknum, (struct sockaddr *) &name, sunlen);
        if (connr == -1) {
            perror("connect");
            return 1;
        }
    }

    // Build buffer;
    constexpr int bufsize = 2;
    char buf[bufsize];

    buf[0] = DINIT_CP_SHUTDOWN;
    buf[1] = static_cast<char>(shutdown_type);

    cout << "Issuing shutdown command..." << endl;

    // TODO make sure to write the whole buffer
    int r = write(socknum, buf, bufsize);
    if (r == -1) {
        perror("write");
        return 1;
    }

    // Wait for ACK/NACK
    // r = read(socknum, buf, 1);
    //if (r > 0) {
    //    cout << "Received acknowledgement. System should now shut down." << endl;
    //}

    CPBuffer<1024> rbuffer;
    try {
        wait_for_reply(rbuffer, socknum);

        if (rbuffer[0] != DINIT_RP_ACK) {
            cerr << "shutdown: control socket protocol error" << endl;
            return 1;
        }
    }
    catch (ReadCPException &exc)
    {
        cerr << "shutdown: control socket read failure or protocol error" << endl;
        return 1;
    }

    while (true) {
        pause();
    }

    return 0;
}

// Fill a circular buffer from a file descriptor, reading at least _rlength_ bytes.
// Throws ReadException if the requested number of bytes cannot be read, with:
//     errcode = 0   if end of stream (remote end closed)
//     errcode = errno   if another error occurred
// Note that EINTR is ignored (i.e. the read will be re-tried).
static void fillBufferTo(CPBuffer<1024> *buf, int fd, int rlength)
{
    do {
        int r = buf->fill_to(fd, rlength);
        if (r == -1) {
            if (errno != EINTR) {
                throw ReadCPException(errno);
            }
        }
        else if (r == 0) {
            throw ReadCPException(0);
        }
        else {
            return;
        }
    }
    while (true);
}

// Wait for a reply packet, skipping over any information packets
// that are received in the meantime.
static void wait_for_reply(CPBuffer<1024> &rbuffer, int fd)
{
    fillBufferTo(&rbuffer, fd, 1);

    while (rbuffer[0] >= 100) {
        // Information packet; discard.
        fillBufferTo(&rbuffer, fd, 1);
        int pktlen = (unsigned char) rbuffer[1];

        rbuffer.consume(1);  // Consume one byte so we'll read one byte of the next packet
        fillBufferTo(&rbuffer, fd, pktlen);
        rbuffer.consume(pktlen - 1);
    }
}

// Actually shut down the system.
void do_system_shutdown(ShutdownType shutdown_type)
{
    using namespace std;

    // Mask all signals to prevent death of our parent etc from terminating us
    sigset_t allsigs;
    sigfillset(&allsigs);
    sigprocmask(SIG_SETMASK, &allsigs, nullptr);

    int reboot_type = 0;
    if (shutdown_type == ShutdownType::REBOOT) reboot_type = RB_AUTOBOOT;
    else if (shutdown_type == ShutdownType::POWEROFF) reboot_type = RB_POWER_OFF;
    else reboot_type = RB_HALT_SYSTEM;

    // Write to console rather than any terminal, since we lose the terminal it seems:
    close(STDOUT_FILENO);
    int consfd = open("/dev/console", O_WRONLY);
    if (consfd != STDOUT_FILENO) {
        dup2(consfd, STDOUT_FILENO);
    }

    cout << "Sending TERM/KILL to all processes..." << endl; // DAV

    // Send TERM/KILL to all (remaining) processes
    kill(-1, SIGTERM);
    sleep(1);
    kill(-1, SIGKILL);

    // perform shutdown
    cout << "Turning off swap..." << endl;
    swap_off();
    cout << "Unmounting disks..." << endl;
    unmount_disks();
    sync();

    cout << "Issuing shutdown via kernel..." << endl;
    reboot(reboot_type);
}

static void unmount_disks()
{
    pid_t chpid = fork();
    if (chpid == 0) {
        // umount -a -r
        //  -a : all filesystems (except proc)
        //  -r : mount readonly if can't unmount
        execl("/bin/umount", "/bin/umount", "-a", "-r", nullptr);
    }
    else if (chpid > 0) {
        int status;
        waitpid(chpid, &status, 0);
    }
}

static void swap_off()
{
    pid_t chpid = fork();
    if (chpid == 0) {
        // swapoff -a
        execl("/sbin/swapoff", "/sbin/swapoff", "-a", nullptr);
    }
    else if (chpid > 0) {
        int status;
        waitpid(chpid, &status, 0);
    }
}
<|endoftext|>


<commit_before>/**
 * @file    kmer_hash.hpp
 * @ingroup bliss::hash
 * @author  tpan
 * @brief   collections of hash functions defined for kmers.
 * @details support the following:  raw bits directly extracted; std::hash version; murmurhash; and farm hash
 *
 *          assuming the use is in a distributed hash table with total buckets N,  N = p * t * l,
 *          where p is number of processes, t is number of threads, and l is number of local buckets.
 *
 *          then the key is assigned to a bucket via hash(key) % N.
 *            the process assignment is: hash(key) / (t * l)
 *            the thread assignment is:  (hash(key) / l) % t
 *            the local bucket assignment is: hash(key) % l;
 *
 *          there are unlikely to be more than 2^64 local buckets, so we can limit the hash(key) % l to be the lower 64bit of hash(key).
 *          this also means that if the hash key is 64 bits, then no shifting or bit masking is needed, which improves performance for local hashtable lookup.
 *
 *          l is a variable that is decided by the local hash table based on number of entries.
 *          we should instead look at the first ceil(log (p*t)) bits of the hash(key).  let's call this "prefix".
 *
 *          process assignment is then:  prefix / t
 *          thread assignment is then:   prefix % t.
 *
 *          prefix for process assignment can be changed to use ceil(log(p)) bits, let's call this "pre-prefix".
 *
 *          process assignment is then:  pre-prefix % p.
 *
 *          2 functions are sufficient then:  prefix_hash(), and suffix_hash().
 *            we restrict our hash() functions to return 64 bits, and make suffix hash() to be the same as hash().
 *
 *
 *          namespace bliss::hash::kmer has a generic hash function that can work with kmer, kmer xor rev comp, computed or provided.
 *          the generic hash function also allows customization via bliss::hash::kmer::detail::{std,identity,murmur,farm} specializations
 *
 *          as stated above, 2 versions for each specialization: hash() and hash_prefix().  the specialization is especially for identity and murmur hashes,
 *          as murmur hash produces 128 bit value, and identity hash uses the original kmer.
 *
 *
 * Copyright (c) 2015 Georgia Institute of Technology.  All Rights Reserved.
 *
 * TODO add License
 */
#ifndef KMER_HASH_HPP_
#define KMER_HASH_HPP_

#include <tuple>  // for hash - std::pair
#include <exception>  // for hash - std::system_error
#include <algorithm>
#include <type_traits>  // enable_if

#include "common/kmer.hpp"

// includ the murmurhash code.
#include "smhasher/MurmurHash3.cpp"
// and farm hash
#include "farmhash.cc"

// Kmer specialization for std::hash
namespace std {
  /**
   * @brief std::hash specialization for kmer.
   * @note  note that WORD_TYPE may be much smaller than uint64_t.  std::hash does a static_cast internally,
   *        so high bits are more likely to be 0.
   *
   *        solution is to reinterpret the data as uint64_t.
   */
  template<unsigned int KMER_SIZE, typename ALPHABET, typename WORD_TYPE>
  struct hash<::bliss::common::Kmer<KMER_SIZE, ALPHABET, WORD_TYPE> > {
      using KmerType = ::bliss::common::Kmer<KMER_SIZE, ALPHABET, WORD_TYPE>;

      static constexpr size_t tuplesize = sizeof(uint64_t) / sizeof(WORD_TYPE);
      static constexpr size_t tuples = KmerType::nWords / tuplesize;
      static constexpr size_t leftover = (tuplesize <= 1) ? 0 : (KmerType::nWords % tuplesize) * sizeof(WORD_TYPE);

      using value_type = KmerType;
      static const unsigned int default_init_value = ::std::min(KmerType::nBits, 64U);
      hash(const unsigned int) {};  // ignored.

      /**
       * @brief function to compute the kmer's hash
       * @details  note that if the kmer uses a word type that is different than uint64_t,
       *        we need to make sure that we use all 64 bits of the hash value..
       *        if the number of bits in kmer is smaller than 64, then we also need to
       *        add an offset.
       *
       *        note that on 32 bit system, this operator does not conform to std::hash declaration.
       *
       * @param kmer
       * @return
       */
      inline uint64_t operator()(value_type const& kmer) const
      {

        // first compute the hash, from 64 bits of input at a time
        uint64_t const * data = reinterpret_cast<uint64_t const*>(kmer.getData());
        uint64_t h = std::hash<uint64_t>()(data[0]);
        uint64_t hp;
        for (size_t i = 1; i < tuples; ++i) {
          hp = std::hash<uint64_t>()(data[i]);
          h ^= (hp << 1);
        }

        // the remainder bits, if any, needs to be dealt with now.
        if (leftover > 0) {
          hp = 0;
          memcpy(&hp, kmer.getData() + tuples * tuplesize, leftover);
          hp = std::hash<uint64_t>()(hp);
          h ^= (hp << 1);
        }

        return h;
      }
  };

}  // namespace std

namespace bliss {

  namespace kmer
  {

    namespace transform {

      // QUESTION:  xor of hash, or hash of xor?.  second is faster.  Also if there is GC-AT imbalance, xor of raw sequence kind of flattens the distribution, so hash input is now more even.

      template <typename KMER>
      struct identity {
          inline KMER operator()(KMER const & x) const {
            return x;
          }
      };

      template <typename KMER>
      struct xor_rev_comp {
          inline KMER operator()(KMER const & x) const {
            return x ^ x.reverse_complement();
          }
          inline KMER operator()(::std::pair<KMER, KMER> const & x) const  {
            return x.first ^ x.second;
          }
      };

      template <typename KMER>
      struct lex_less {
          inline KMER operator()(KMER const & x) const  {
            auto y = x.reverse_complement();
            return (x < y) ? x : y;
          }
          inline KMER operator()(::std::pair<KMER, KMER> const & x) const  {
            return (x.first < x.second) ? x.first : x.second;
          }
      };

      template <typename KMER>
      struct lex_greater {
          inline KMER operator()(KMER const & x) const  {
            auto y = x.reverse_complement();
            return (x > y) ? x : y;
          }
          inline KMER operator()(::std::pair<KMER, KMER> const & x) const  {
            return (x.first > x.second) ? x.first : x.second;
          }
      };

    } // namespace transform

    namespace hash
    {

      /**
       * @brief  Kmer hash, returns the least significant NumBits directly as identity hash.
       * @note   since the number of buckets is not known ahead of time, can't have nbit be a type.  max is 64bits.
       */
      template<typename KMER, bool Prefix = false>
      class cpp_std {
        protected:
          int64_t shift;
        public:
          static constexpr unsigned int default_init_value = ::std::min(KMER::nBits, 64U);

          cpp_std(const unsigned int prefix_bits = default_init_value) : shift(default_init_value - prefix_bits) {
            if (prefix_bits > default_init_value)  throw ::std::invalid_argument("ERROR: prefix larger than available hash size or kmer size.");
          };

          /// operator to compute hash
          inline size_t operator()(const KMER & kmer) const {
            if (Prefix)
              // if multiword, nBits > 64, then the returned hash will have meaningful msb.  min(nBits, 64) == 64.
              // if single word, nBits <= 64, then min(nBits, 64) = nBits, and shift is the right thing.
              return ::std::hash<KMER>(kmer) >> shift;
            else
              // if multiword, nBits > 64, then the returned hash will have meaningful msb.  min(nBits, 64) == 64.
              // if single word, nBits <= 64, then min(nBits, 64) = nBits, and shift is the right thing.
              return ::std::hash<KMER>(kmer);
          }

      };

      /**
       * @brief  Kmer hash, returns the least significant NumBits directly as identity hash.
       * @note   since the number of buckets is not known ahead of time, can't have nbit be a type
       */
      template <typename KMER, bool Prefix = false>
      class identity {

        protected:
          unsigned int bits;
        public:
          static const unsigned int default_init_value = ::std::min(KMER::nBits, 64U);

          /// constructor
          identity(const unsigned int prefix_bits = default_init_value) : bits(prefix_bits) {
            if ((prefix_bits == 0) || (prefix_bits > default_init_value)) throw ::std::invalid_argument("ERROR: prefix size outside of supported range");
          };

          /// operator to compute hash value
          inline uint64_t operator()(const KMER & kmer) const {
            if (Prefix)
              return kmer.getPrefix(bits);  // get the first bits number of bits from kmer.
            else
              // if nBits < 64U, then it's padded with 0.  just get it.  else we want the entire 64bit.
              return kmer.getSuffix(default_init_value);
          }
      };

      /**
       * @brief Kmer specialization for MurmurHash.  generated hash is 128 bit.
       */
      template <typename KMER, bool Prefix = false>
      class murmur {

        protected:
          static constexpr unsigned int nBytes = (KMER::nBits + 7) / 8;

        public:
          murmur(const unsigned int) {};

          inline uint64_t operator()(KMER const& kmer) const
          {
            // produces 128 bit hash.
            uint64_t h[2];
            // let compiler optimize out all except one of these.
            if (sizeof(void*) == 8)
              MurmurHash3_x64_128(kmer.getData(), nBytes, 42, h);
            else if (sizeof(void*) == 4)
              MurmurHash3_x86_128(kmer.getData(), nBytes, 42, h);
            else
              throw ::std::logic_error("ERROR: neither 32 bit nor 64 bit system");

            // use the upper 64 bits.
            if (Prefix)
              return h[1];
            else
              return h[0];
          }

      };

      /**
       * @brief  Kmer hash, returns the least significant NumBits from murmur hash.
       * @note   since the number of buckets is not known ahead of time, can't have nbit be a type
       *
       * @tparam Prefix:  to get prefix,
       */
      template <typename KMER, bool Prefix = false>
      class farm {

        protected:
          static constexpr unsigned int nBytes = (KMER::nBits + 7) / 8;
          size_t shift;

        public:
          static const unsigned int default_init_value = 64U;

          farm(const unsigned int prefix_bits = default_init_value) : shift(64U - prefix_bits) {
            if (prefix_bits > default_init_value)  throw ::std::invalid_argument("ERROR: prefix larger than 64 bit.");
          };

          /// operator to compute hash.  64 bit again.
          inline uint64_t operator()(const KMER & kmer) const {
            if (Prefix)
              return ::util::Hash(reinterpret_cast<const char*>(kmer.getData()), nBytes) >> shift;
            else
              return ::util::Hash(reinterpret_cast<const char*>(kmer.getData()), nBytes);
          }

      };

      // usage  apply transform first, then apply hash.
    } // namespace hash
  } // namespace kmer
} // namespace bliss

#endif /* KMER_HASH_HPP_ */
<commit_msg>ENH: removed std::hash<Kmer> which is not really used.  ENH: added tuple transform class for transforming a vector of pairs that includes a kmer or kmers.  FIX: murmur hash constructor causing build issue<commit_after>/**
 * @file    kmer_hash.hpp
 * @ingroup bliss::hash
 * @author  tpan
 * @brief   collections of hash functions defined for kmers.
 * @details support the following:  raw bits directly extracted; std::hash version; murmurhash; and farm hash
 *
 *          assuming the use is in a distributed hash table with total buckets N,  N = p * t * l,
 *          where p is number of processes, t is number of threads, and l is number of local buckets.
 *
 *          then the key is assigned to a bucket via hash(key) % N.
 *            the process assignment is: hash(key) / (t * l)
 *            the thread assignment is:  (hash(key) / l) % t
 *            the local bucket assignment is: hash(key) % l;
 *
 *          there are unlikely to be more than 2^64 local buckets, so we can limit the hash(key) % l to be the lower 64bit of hash(key).
 *          this also means that if the hash key is 64 bits, then no shifting or bit masking is needed, which improves performance for local hashtable lookup.
 *
 *          l is a variable that is decided by the local hash table based on number of entries.
 *          we should instead look at the first ceil(log (p*t)) bits of the hash(key).  let's call this "prefix".
 *
 *          process assignment is then:  prefix / t
 *          thread assignment is then:   prefix % t.
 *
 *          prefix for process assignment can be changed to use ceil(log(p)) bits, let's call this "pre-prefix".
 *
 *          process assignment is then:  pre-prefix % p.
 *
 *          2 functions are sufficient then:  prefix_hash(), and suffix_hash().
 *            we restrict our hash() functions to return 64 bits, and make suffix hash() to be the same as hash().
 *
 *
 *          namespace bliss::hash::kmer has a generic hash function that can work with kmer, kmer xor rev comp, computed or provided.
 *          the generic hash function also allows customization via bliss::hash::kmer::detail::{std,identity,murmur,farm} specializations
 *
 *          as stated above, 2 versions for each specialization: hash() and hash_prefix().  the specialization is especially for identity and murmur hashes,
 *          as murmur hash produces 128 bit value, and identity hash uses the original kmer.
 *
 *
 * Copyright (c) 2015 Georgia Institute of Technology.  All Rights Reserved.
 *
 * TODO add License
 */
#ifndef KMER_HASH_HPP_
#define KMER_HASH_HPP_

#include <tuple>  // for hash - std::pair
#include <exception>  // for hash - std::system_error
#include <algorithm>
#include <type_traits>  // enable_if

#include "common/kmer.hpp"

// includ the murmurhash code.
#include "smhasher/MurmurHash3.cpp"
// and farm hash
#include "farmhash.cc"

//// Kmer specialization for std::hash
//namespace std {
//  /**
//   * @brief std::hash specialization for kmer.
//   * @note  note that WORD_TYPE may be much smaller than uint64_t.  std::hash does a static_cast internally,
//   *        so high bits are more likely to be 0.
//   *
//   *        solution is to reinterpret the data as uint64_t.
//   */
//  template<unsigned int KMER_SIZE, typename ALPHABET, typename WORD_TYPE>
//  struct hash<::bliss::common::Kmer<KMER_SIZE, ALPHABET, WORD_TYPE> > {
//      using KmerType = ::bliss::common::Kmer<KMER_SIZE, ALPHABET, WORD_TYPE>;
//
//      static constexpr size_t tuples = KmerType::nBytes / sizeof(uint64_t);
//      static constexpr size_t leftover = KmerType::nBytes % sizeof(uint64_t);
//
//      using value_type = KmerType;
//      static const unsigned int default_init_value = KmerType::nBits < 64U ? KmerType::nBits : 64U;
//
//
//      /**
//       * @brief function to compute the kmer's hash
//       * @details  note that if the kmer uses a word type that is different than uint64_t,
//       *        we need to make sure that we use all 64 bits of the hash value..
//       *        if the number of bits in kmer is smaller than 64, then we also need to
//       *        add an offset.
//       *
//       *        note that on 32 bit system, this operator does not conform to std::hash declaration.
//       *
//       * @param kmer
//       * @return
//       */
//      inline uint64_t operator()(value_type const& kmer) const
//      {
//
//        // first compute the hash, from 64 bits of input at a time
//        uint64_t const * data = reinterpret_cast<uint64_t const*>(kmer.getData());
//        uint64_t h = std::hash<uint64_t>()(data[0]);
//        uint64_t hp;
//        for (size_t i = 1; i < tuples; ++i) {
//          hp = std::hash<uint64_t>()(data[i]);
//          h ^= (hp << 1);
//        }
//
//        // the remainder bits, if any, needs to be dealt with now.
//        if (leftover > 0) {
//          hp = 0;
//          memcpy(&hp, kmer.getData() + tuples * sizeof(uint64_t), leftover);
//          hp = std::hash<uint64_t>()(hp);
//          h ^= (hp << 1);
//        }
//
//        return h;
//      }
//  };
//
//
//}  // namespace std
//

namespace bliss {

  namespace kmer
  {

    namespace transform {

      // QUESTION:  xor of hash, or hash of xor?.  second is faster.  Also if there is GC-AT imbalance, xor of raw sequence kind of flattens the distribution, so hash input is now more even.

      template <typename KMER>
      struct identity {
          inline KMER operator()(KMER const & x) const {
            return x;
          }
      };

      template <typename KMER>
      struct xor_rev_comp {
          inline KMER operator()(KMER const & x) const {
            return x ^ x.reverse_complement();
          }
          inline KMER operator()(::std::pair<KMER, KMER> const & x) const  {
            return x.first ^ x.second;
          }
      };

      template <typename KMER>
      struct lex_less {
          inline KMER operator()(KMER const & x) const  {
            auto y = x.reverse_complement();
            return (x < y) ? x : y;
          }
          inline KMER operator()(::std::pair<KMER, KMER> const & x) const  {
            return (x.first < x.second) ? x.first : x.second;
          }
      };

      template <typename KMER>
      struct lex_greater {
          inline KMER operator()(KMER const & x) const  {
            auto y = x.reverse_complement();
            return (x > y) ? x : y;
          }
          inline KMER operator()(::std::pair<KMER, KMER> const & x) const  {
            return (x.first > x.second) ? x.first : x.second;
          }
      };

      template <typename KMER, template <typename KMER> class TRANS>
      struct tuple_transform {
          TRANS<KMER> transform;

          inline KMER operator()(KMER & x) {
            x = transform(x);
            return x;
          }

          template <typename VAL>
          inline ::std::pair<KMER, VAL> operator()(std::pair<KMER, VAL> & x) {
            x.first = transform(x.first);
            return x;
          }

      };

    } // namespace transform

    namespace hash
    {

      /**
       * @brief  Kmer hash, returns the least significant NumBits directly as identity hash.
       * @note   since the number of buckets is not known ahead of time, can't have nbit be a type.  max is 64bits.
       */
      template<typename KMER, bool Prefix = false>
      class cpp_std {
        protected:
          static constexpr size_t tuples = KMER::nWords * sizeof(typename KMER::KmerWordType) / sizeof(uint64_t);
          static constexpr size_t leftover = KMER::nWords * sizeof(typename KMER::KmerWordType) % sizeof(uint64_t);

          int64_t shift;
        public:
          static constexpr unsigned int default_init_value = (KMER::nBits < 64U) ? KMER::nBits : 64U;

          cpp_std(const unsigned int prefix_bits = default_init_value) : shift(default_init_value - prefix_bits) {
            if (prefix_bits > default_init_value)  throw ::std::invalid_argument("ERROR: prefix larger than available hash size or kmer size.");
          };

          /// operator to compute hash
          inline size_t operator()(const KMER & kmer) const {

            // first compute the hash, from 64 bits of input at a time
            size_t const * data = reinterpret_cast<size_t const*>(kmer.getData());
            size_t h = std::hash<size_t>()(data[0]);
            size_t hp;
            for (size_t i = 1; i < tuples; ++i) {
              hp = std::hash<size_t>()(data[i]);
              h ^= (hp << 1);
            }

            // the remainder bits, if any, needs to be dealt with now.
            if (leftover > 0) {
              hp = 0;
              memcpy(&hp, kmer.getData() + tuples * sizeof(size_t), leftover);
              hp = std::hash<size_t>()(hp);
              h ^= (hp << 1);
            }

            if (Prefix)
              // if multiword, nBits > 64, then the returned hash will have meaningful msb.  min(nBits, 64) == 64.
              // if single word, nBits <= 64, then min(nBits, 64) = nBits, and shift is the right thing.
              return h >> shift;
            else
              // if multiword, nBits > 64, then the returned hash will have meaningful msb.  min(nBits, 64) == 64.
              // if single word, nBits <= 64, then min(nBits, 64) = nBits, and shift is the right thing.
              return h;
          }

      };

      /**
       * @brief  Kmer hash, returns the least significant NumBits directly as identity hash.
       * @note   since the number of buckets is not known ahead of time, can't have nbit be a type
       */
      template <typename KMER, bool Prefix = false>
      class identity {

        protected:
          unsigned int bits;
        public:
          static const unsigned int default_init_value = KMER::nBits < 64U ? KMER::nBits : 64U;

          /// constructor
          identity(const unsigned int prefix_bits = default_init_value) : bits(prefix_bits) {
            if ((prefix_bits == 0) || (prefix_bits > default_init_value)) throw ::std::invalid_argument("ERROR: prefix size outside of supported range");
          };

          /// operator to compute hash value
          inline uint64_t operator()(const KMER & kmer) const {
            if (Prefix)
              return kmer.getPrefix(bits);  // get the first bits number of bits from kmer.
            else
              // if nBits < 64U, then it's padded with 0.  just get it.  else we want the entire 64bit.
              return kmer.getSuffix(default_init_value);
          }
      };

      /**
       * @brief Kmer specialization for MurmurHash.  generated hash is 128 bit.
       */
      template <typename KMER, bool Prefix = false>
      class murmur {

        protected:
          static constexpr unsigned int nBytes = (KMER::nBits + 7) / 8;

        public:
          static const unsigned int default_init_value = 64U;

          murmur(const unsigned int prefix_bits = default_init_value) {};

          inline uint64_t operator()(const KMER & kmer) const
          {
            // produces 128 bit hash.
            uint64_t h[2];
            // let compiler optimize out all except one of these.
            if (sizeof(void*) == 8)
              MurmurHash3_x64_128(kmer.getData(), nBytes, 42, h);
            else if (sizeof(void*) == 4)
              MurmurHash3_x86_128(kmer.getData(), nBytes, 42, h);
            else
              throw ::std::logic_error("ERROR: neither 32 bit nor 64 bit system");

            // use the upper 64 bits.
            if (Prefix)
              return h[1];
            else
              return h[0];
          }

      };

      /**
       * @brief  Kmer hash, returns the least significant NumBits from murmur hash.
       * @note   since the number of buckets is not known ahead of time, can't have nbit be a type
       *
       * @tparam Prefix:  to get prefix,
       */
      template <typename KMER, bool Prefix = false>
      class farm {

        protected:
          static constexpr unsigned int nBytes = (KMER::nBits + 7) / 8;
          size_t shift;

        public:
          static const unsigned int default_init_value = 64U;

          farm(const unsigned int prefix_bits = default_init_value) : shift(64U - prefix_bits) {
            if (prefix_bits > default_init_value)  throw ::std::invalid_argument("ERROR: prefix larger than 64 bit.");
          };

          /// operator to compute hash.  64 bit again.
          inline uint64_t operator()(const KMER & kmer) const {
            if (Prefix)
              return ::util::Hash(reinterpret_cast<const char*>(kmer.getData()), nBytes) >> shift;
            else
              return ::util::Hash(reinterpret_cast<const char*>(kmer.getData()), nBytes);
          }

      };

      // usage  apply transform first, then apply hash.
    } // namespace hash
  } // namespace kmer
} // namespace bliss

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


<commit_before>// Copyright (C) 2014, Baidu Inc.
// Author: Xu Peilin (xupeilin@baidu.com)
//
// Description:
//

#include "jni_tera_common.h"

#include "common/file/file_path.h"
#include "glog/logging.h"

#include "utils/utils_cmd.h"

DECLARE_string(flagfile);
DECLARE_string(log_dir);

DECLARE_string(tera_user_identity);
DECLARE_string(tera_user_passcode);

void SendErrorJ(JNIEnv *env, jobject jobj, std::string msg) {
    jclass jc = env->GetObjectClass(jobj);
    jstring jmsg = env->NewStringUTF(msg.c_str());
    env->SetObjectField(jobj,
                        env->GetFieldID(jc, "nativeMsg", "Ljava/lang/String;"),
                        jmsg);
    LOG(ERROR) << msg;
}

void InitFlags(std::string confpath) {
    // init FLAGS_flagfile
    if (IsExist(confpath)) {
        FLAGS_flagfile = confpath;
    } else if (IsExist("./tera.flag")) {
        FLAGS_flagfile = "./tera.flag";
    } else {
        LOG(FATAL) << "tera.flag not exist, job failed.";
    }

    // init user identity & role
    std::string cur_identity = tera::utils::GetValueFromeEnv("USER");
    if (cur_identity.empty()) {
        cur_identity = "other";
    }
    if (FLAGS_tera_user_identity.empty()) {
        FLAGS_tera_user_identity = cur_identity;
    }

    // init log dir
    if (FLAGS_log_dir.empty()) {
        FLAGS_log_dir = "./";
    }
    ::google::ReadFromFlagsFile(FLAGS_flagfile, NULL, true);
    LOG(INFO) << "USER = " << FLAGS_tera_user_identity;
    LOG(INFO) << "Load config file: " << FLAGS_flagfile;
}

void InitGlog(std::string prefix) {
    ::google::InitGoogleLogging(prefix.c_str());
}

std::string ConvertDescToString(tera::TableDescriptor* desc) {
    return "desc";

}

void JByteArrayToString(JNIEnv *env, jbyteArray& jbarray, std::string* str) {
    const char* str_ptr =
        reinterpret_cast<const char*>(env->GetByteArrayElements(jbarray, 0));
    size_t str_len =
        static_cast<size_t>(env->GetArrayLength(jbarray));
    str->assign(str_ptr, str_len);
}

void StringToJByteArray(JNIEnv *env, const std::string& str, jbyteArray* jbarray) {
    size_t str_len = str.size();
    *jbarray = env->NewByteArray(str_len);
    jbyte* buffer = env->GetByteArrayElements(*jbarray, 0);
    memcpy(buffer, str.data(), str_len);
    env->SetByteArrayRegion(*jbarray, 0, str_len, buffer);
}
<commit_msg>Update jni_tera_common.cc<commit_after>// Copyright (C) 2014, Baidu Inc.
// Author: Xu Peilin (xupeilin@baidu.com)
//
// Description:
//

#include "jni_tera_common.h"

#include "common/file/file_path.h"
#include "gflags/gflags.h"
#include "glog/logging.h"

#include "utils/utils_cmd.h"

DECLARE_string(flagfile);
DECLARE_string(log_dir);

DECLARE_string(tera_user_identity);
DECLARE_string(tera_user_passcode);

void SendErrorJ(JNIEnv *env, jobject jobj, std::string msg) {
    jclass jc = env->GetObjectClass(jobj);
    jstring jmsg = env->NewStringUTF(msg.c_str());
    env->SetObjectField(jobj,
                        env->GetFieldID(jc, "nativeMsg", "Ljava/lang/String;"),
                        jmsg);
    LOG(ERROR) << msg;
}

void InitFlags(std::string confpath) {
    // init FLAGS_flagfile
    if (IsExist(confpath)) {
        FLAGS_flagfile = confpath;
    } else if (IsExist("./tera.flag")) {
        FLAGS_flagfile = "./tera.flag";
    } else {
        LOG(FATAL) << "tera.flag not exist, job failed.";
    }

    // init user identity & role
    std::string cur_identity = tera::utils::GetValueFromeEnv("USER");
    if (cur_identity.empty()) {
        cur_identity = "other";
    }
    if (FLAGS_tera_user_identity.empty()) {
        FLAGS_tera_user_identity = cur_identity;
    }

    // init log dir
    if (FLAGS_log_dir.empty()) {
        FLAGS_log_dir = "./";
    }
    ::google::ReadFromFlagsFile(FLAGS_flagfile, NULL, true);
    LOG(INFO) << "USER = " << FLAGS_tera_user_identity;
    LOG(INFO) << "Load config file: " << FLAGS_flagfile;
}

void InitGlog(std::string prefix) {
    ::google::InitGoogleLogging(prefix.c_str());
}

std::string ConvertDescToString(tera::TableDescriptor* desc) {
    return "desc";

}

void JByteArrayToString(JNIEnv *env, jbyteArray& jbarray, std::string* str) {
    const char* str_ptr =
        reinterpret_cast<const char*>(env->GetByteArrayElements(jbarray, 0));
    size_t str_len =
        static_cast<size_t>(env->GetArrayLength(jbarray));
    str->assign(str_ptr, str_len);
}

void StringToJByteArray(JNIEnv *env, const std::string& str, jbyteArray* jbarray) {
    size_t str_len = str.size();
    *jbarray = env->NewByteArray(str_len);
    jbyte* buffer = env->GetByteArrayElements(*jbarray, 0);
    memcpy(buffer, str.data(), str_len);
    env->SetByteArrayRegion(*jbarray, 0, str_len, buffer);
}
<|endoftext|>