<commit_before>#include "json_rpc_server.h"
#include "json_rpc.h"
#include "stinger_core/xmalloc.h"
#include "rapidjson/document.h"

#define LOG_AT_W  /* warning only */
#include "stinger_core/stinger_error.h"

using namespace gt::stinger;

int64_t
JSON_RPC_egonet::operator()(rapidjson::Value * params, rapidjson::Value & result, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> & allocator)
{
  int64_t source;
  bool strings;
  bool get_types;
  bool get_etypes;
  bool get_vtypes;
  bool incident_edges;

  rpc_params_t p[] = {
    {"source", TYPE_VERTEX, &source, false, 0},
    {"strings", TYPE_BOOL, &strings, true, 0},
    {"get_types", TYPE_BOOL, &get_types, true, 0},
    {"get_etypes", TYPE_BOOL, &get_etypes, true, 0},
    {"get_vtypes", TYPE_BOOL, &get_vtypes, true, 0},
    {"incident_edges", TYPE_BOOL, &incident_edges, true, 0},
    {NULL, TYPE_NONE, NULL, false, 0}
  };

  if (!contains_params(p, params)) {
    return json_rpc_error(-32602, result, allocator);
  }

  if(get_types) {
    get_etypes = true;
    get_vtypes = true;
  }

  stinger_t * S = server_state->get_stinger();
  if (!S) {
    LOG_E ("STINGER pointer is invalid");
    return json_rpc_error(-32603, result, allocator);
  }

  /* find a vertex with more than 10 edges and less than 50 */
  int64_t max_nv = S->max_nv;
  int64_t selected_vertex = -1;
  for (int64_t i = 0; i < max_nv; i++) {
    int64_t outdegree = stinger_outdegree(S, i);
    if (outdegree < 50 && outdegree > 10) {
      selected_vertex = i;
      break;
    }
  }
  source = selected_vertex;

  /* array to hold a single edge */
  rapidjson::Value val(rapidjson::kArrayType);

  /* array to hold all edges (virtually addressed) */
  rapidjson::Value edges(rapidjson::kArrayType);

  /* array to hold all edges (physically addressed) */
  rapidjson::Value edges_str(rapidjson::kArrayType);

  /* array to hold all vertices (virtually addressed) */
  rapidjson::Value vtx(rapidjson::kArrayType);

  /* array to hold all vertices (physically addressed) */
  rapidjson::Value vtx_str(rapidjson::kArrayType);

  /* values to hold vertex information */
  rapidjson::Value vtype, vtype_str;
  rapidjson::Value center, center_str;
  rapidjson::Value src, dst;
  rapidjson::Value src_str, dst_str;
  rapidjson::Value etype, etype_str;

  /* array to hold vertex types */
  rapidjson::Value vtypes(rapidjson::kArrayType);

  /* array to hold vertex type strings */
  rapidjson::Value vtypes_str(rapidjson::kArrayType);

  /* vertex has no edges -- this is easy */
  if (stinger_outdegree (S, source) == 0) {
    result.AddMember("egonet", edges, allocator);
    return 0;
  }

  /* this array will hold the neighbor set */
  int64_t nv = S->max_nv;
  int64_t * marks = (int64_t *) xmalloc (nv * sizeof(int64_t));
  for (int64_t i = 0; i < nv; i++) {
    marks[i] = 0;
  }

  /* mark and insert source if we are returning incident edges */
  if (incident_edges) {
    marks[source] = 1;
    center.SetInt64(source);
    vtx.PushBack(center, allocator);

    if (strings) {
      char * physID;
      uint64_t len;
      if (-1 == stinger_mapping_physid_direct(S, source, &physID, &len)) {
	physID = (char *) "";
	len = 0;
      }
      center_str.SetString(physID, len, allocator);
      vtx_str.PushBack(center_str, allocator);
    }

    if (get_vtypes) {
      int64_t source_type = stinger_vtype_get(S, source);
      vtype.SetInt64(source_type);
      vtypes.PushBack(vtype, allocator);

      if (strings) {
	char * name = NULL;
	uint64_t len = 0;
	char * vtype_name = stinger_vtype_names_lookup_name(S, source_type);
	vtype_str.SetString(vtype_name, strlen(vtype_name), allocator);
	vtypes_str.PushBack(vtype_str, allocator);
      }
    }
  }

  /* mark all neighbors of the source vertex */
  STINGER_FORALL_EDGES_OF_VTX_BEGIN (S, source) {
    int64_t u = STINGER_EDGE_DEST;
    marks[u] = 1;
    src.SetInt64(u);
    vtx.PushBack(src, allocator);

    if (strings) {
      char * physID;
      uint64_t len;
      if (-1 == stinger_mapping_physid_direct(S, u, &physID, &len)) {
	physID = (char *) "";
	len = 0;
      }
      src_str.SetString(physID, len, allocator);
      vtx_str.PushBack(src_str, allocator);
    }

    if (incident_edges) {
      src.SetInt64(source);
      dst.SetInt64(u);
      val.SetArray();
      val.PushBack(src, allocator);
      val.PushBack(dst, allocator);
      if (get_etypes) {
	etype.SetInt64(STINGER_EDGE_TYPE);
	val.PushBack(etype, allocator);
      }
      edges.PushBack(val, allocator);

      if (strings) {
	char * physID;
	uint64_t len;
	if (-1 == stinger_mapping_physid_direct(S, source, &physID, &len)) {
	  physID = (char *) "";
	  len = 0;
	}
	src_str.SetString(physID, len, allocator);

	if (-1 == stinger_mapping_physid_direct(S, u, &physID, &len)) {
	  physID = (char *) "";
	  len = 0;
	}
	dst_str.SetString(physID, len, allocator);

	val.SetArray();
	val.PushBack(src_str, allocator);
	val.PushBack(dst_str, allocator);
	if (get_etypes) {
	  char * etype_str_ptr = stinger_etype_names_lookup_name(S, STINGER_EDGE_TYPE);
	  etype_str.SetString(etype_str_ptr, strlen(etype_str_ptr), allocator);
	  val.PushBack(etype_str, allocator);
	}
	edges_str.PushBack(val, allocator);
      }
    }

    if (get_vtypes) {
      int64_t source_type = stinger_vtype_get(S, u);
      vtype.SetInt64(source_type);
      vtypes.PushBack(vtype, allocator);

      if (strings) {
	char * name = NULL;
	uint64_t len = 0;
	char * vtype_name = stinger_vtype_names_lookup_name(S, source_type);
	vtype_str.SetString(vtype_name, strlen(vtype_name), allocator);
	vtypes_str.PushBack(vtype_str, allocator);
      }
    }

  } STINGER_FORALL_EDGES_OF_VTX_END();

  /* now we will find all of the edges in common between the neighbors */
  STINGER_FORALL_EDGES_OF_VTX_BEGIN (S, source) {
    int64_t u = STINGER_EDGE_DEST;

    STINGER_FORALL_EDGES_OF_VTX_BEGIN (S, u) {
      int64_t v = STINGER_EDGE_DEST;

      if (marks[v]) {
	src.SetInt64(u);
	dst.SetInt64(v);
	val.SetArray();
	val.PushBack(src, allocator);
	val.PushBack(dst, allocator);
	if (get_etypes) {
	  etype.SetInt64(STINGER_EDGE_TYPE);
	  val.PushBack(etype, allocator);
	}
	edges.PushBack(val, allocator);

	if (strings) {
	  char * physID;
	  uint64_t len;
	  if (-1 == stinger_mapping_physid_direct(S, u, &physID, &len)) {
	    physID = (char *) "";
	    len = 0;
	  }
	  src_str.SetString(physID, len, allocator);

	  if (-1 == stinger_mapping_physid_direct(S, v, &physID, &len)) {
	    physID = (char *) "";
	    len = 0;
	  }
	  dst_str.SetString(physID, len, allocator);
	  val.SetArray();
	  val.PushBack(src_str, allocator);
	  val.PushBack(dst_str, allocator);
	  if (get_etypes) {
	    char * etype_str_ptr = stinger_etype_names_lookup_name(S, STINGER_EDGE_TYPE);
	    etype_str.SetString(etype_str_ptr, strlen(etype_str_ptr), allocator);
	    val.PushBack(etype_str, allocator);
	  }
	  edges_str.PushBack(val, allocator);
	}
      }

    } STINGER_FORALL_EDGES_OF_VTX_END();
  } STINGER_FORALL_EDGES_OF_VTX_END();

  result.AddMember("vertices", vtx, allocator);
  if (strings) {
    result.AddMember("vertices_str", vtx_str, allocator);
  }

  if (get_vtypes) {
    result.AddMember("vtypes", vtypes, allocator);
    if (strings) {
      result.AddMember("vtypes_str", vtypes_str, allocator);
    }
  }

  result.AddMember("egonet", edges, allocator);
  if (strings) {
    result.AddMember("egonet_str", edges_str, allocator);
  }

  free(marks);

  return 0;
}

<commit_msg>Revert "Breaking egonet to only show a random vertex with outdegree between 10 and 50."<commit_after>#include "json_rpc_server.h"
#include "json_rpc.h"
#include "stinger_core/xmalloc.h"
#include "rapidjson/document.h"

#define LOG_AT_W  /* warning only */
#include "stinger_core/stinger_error.h"

using namespace gt::stinger;

int64_t
JSON_RPC_egonet::operator()(rapidjson::Value * params, rapidjson::Value & result, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> & allocator)
{
  int64_t source;
  bool strings;
  bool get_types;
  bool get_etypes;
  bool get_vtypes;
  bool incident_edges;

  rpc_params_t p[] = {
    {"source", TYPE_VERTEX, &source, false, 0},
    {"strings", TYPE_BOOL, &strings, true, 0},
    {"get_types", TYPE_BOOL, &get_types, true, 0},
    {"get_etypes", TYPE_BOOL, &get_etypes, true, 0},
    {"get_vtypes", TYPE_BOOL, &get_vtypes, true, 0},
    {"incident_edges", TYPE_BOOL, &incident_edges, true, 0},
    {NULL, TYPE_NONE, NULL, false, 0}
  };

  if (!contains_params(p, params)) {
    return json_rpc_error(-32602, result, allocator);
  }

  if(get_types) {
    get_etypes = true;
    get_vtypes = true;
  }

  stinger_t * S = server_state->get_stinger();
  if (!S) {
    LOG_E ("STINGER pointer is invalid");
    return json_rpc_error(-32603, result, allocator);
  }

  /* array to hold a single edge */
  rapidjson::Value val(rapidjson::kArrayType);

  /* array to hold all edges (virtually addressed) */
  rapidjson::Value edges(rapidjson::kArrayType);

  /* array to hold all edges (physically addressed) */
  rapidjson::Value edges_str(rapidjson::kArrayType);

  /* array to hold all vertices (virtually addressed) */
  rapidjson::Value vtx(rapidjson::kArrayType);

  /* array to hold all vertices (physically addressed) */
  rapidjson::Value vtx_str(rapidjson::kArrayType);

  /* values to hold vertex information */
  rapidjson::Value vtype, vtype_str;
  rapidjson::Value center, center_str;
  rapidjson::Value src, dst;
  rapidjson::Value src_str, dst_str;
  rapidjson::Value etype, etype_str;

  /* array to hold vertex types */
  rapidjson::Value vtypes(rapidjson::kArrayType);

  /* array to hold vertex type strings */
  rapidjson::Value vtypes_str(rapidjson::kArrayType);

  /* vertex has no edges -- this is easy */
  if (stinger_outdegree (S, source) == 0) {
    result.AddMember("egonet", edges, allocator);
    return 0;
  }

  /* this array will hold the neighbor set */
  int64_t nv = S->max_nv;
  int64_t * marks = (int64_t *) xmalloc (nv * sizeof(int64_t));
  for (int64_t i = 0; i < nv; i++) {
    marks[i] = 0;
  }

  /* mark and insert source if we are returning incident edges */
  if (incident_edges) {
    marks[source] = 1;
    center.SetInt64(source);
    vtx.PushBack(center, allocator);

    if (strings) {
      char * physID;
      uint64_t len;
      if (-1 == stinger_mapping_physid_direct(S, source, &physID, &len)) {
	physID = (char *) "";
	len = 0;
      }
      center_str.SetString(physID, len, allocator);
      vtx_str.PushBack(center_str, allocator);
    }

    if (get_vtypes) {
      int64_t source_type = stinger_vtype_get(S, source);
      vtype.SetInt64(source_type);
      vtypes.PushBack(vtype, allocator);

      if (strings) {
	char * name = NULL;
	uint64_t len = 0;
	char * vtype_name = stinger_vtype_names_lookup_name(S, source_type);
	vtype_str.SetString(vtype_name, strlen(vtype_name), allocator);
	vtypes_str.PushBack(vtype_str, allocator);
      }
    }
  }

  /* mark all neighbors of the source vertex */
  STINGER_FORALL_EDGES_OF_VTX_BEGIN (S, source) {
    int64_t u = STINGER_EDGE_DEST;
    marks[u] = 1;
    src.SetInt64(u);
    vtx.PushBack(src, allocator);

    if (strings) {
      char * physID;
      uint64_t len;
      if (-1 == stinger_mapping_physid_direct(S, u, &physID, &len)) {
	physID = (char *) "";
	len = 0;
      }
      src_str.SetString(physID, len, allocator);
      vtx_str.PushBack(src_str, allocator);
    }

    if (incident_edges) {
      src.SetInt64(source);
      dst.SetInt64(u);
      val.SetArray();
      val.PushBack(src, allocator);
      val.PushBack(dst, allocator);
      if (get_etypes) {
	etype.SetInt64(STINGER_EDGE_TYPE);
	val.PushBack(etype, allocator);
      }
      edges.PushBack(val, allocator);

      if (strings) {
	char * physID;
	uint64_t len;
	if (-1 == stinger_mapping_physid_direct(S, source, &physID, &len)) {
	  physID = (char *) "";
	  len = 0;
	}
	src_str.SetString(physID, len, allocator);

	if (-1 == stinger_mapping_physid_direct(S, u, &physID, &len)) {
	  physID = (char *) "";
	  len = 0;
	}
	dst_str.SetString(physID, len, allocator);

	val.SetArray();
	val.PushBack(src_str, allocator);
	val.PushBack(dst_str, allocator);
	if (get_etypes) {
	  char * etype_str_ptr = stinger_etype_names_lookup_name(S, STINGER_EDGE_TYPE);
	  etype_str.SetString(etype_str_ptr, strlen(etype_str_ptr), allocator);
	  val.PushBack(etype_str, allocator);
	}
	edges_str.PushBack(val, allocator);
      }
    }

    if (get_vtypes) {
      int64_t source_type = stinger_vtype_get(S, u);
      vtype.SetInt64(source_type);
      vtypes.PushBack(vtype, allocator);

      if (strings) {
	char * name = NULL;
	uint64_t len = 0;
	char * vtype_name = stinger_vtype_names_lookup_name(S, source_type);
	vtype_str.SetString(vtype_name, strlen(vtype_name), allocator);
	vtypes_str.PushBack(vtype_str, allocator);
      }
    }

  } STINGER_FORALL_EDGES_OF_VTX_END();

  /* now we will find all of the edges in common between the neighbors */
  STINGER_FORALL_EDGES_OF_VTX_BEGIN (S, source) {
    int64_t u = STINGER_EDGE_DEST;

    STINGER_FORALL_EDGES_OF_VTX_BEGIN (S, u) {
      int64_t v = STINGER_EDGE_DEST;

      if (marks[v]) {
	src.SetInt64(u);
	dst.SetInt64(v);
	val.SetArray();
	val.PushBack(src, allocator);
	val.PushBack(dst, allocator);
	if (get_etypes) {
	  etype.SetInt64(STINGER_EDGE_TYPE);
	  val.PushBack(etype, allocator);
	}
	edges.PushBack(val, allocator);

	if (strings) {
	  char * physID;
	  uint64_t len;
	  if (-1 == stinger_mapping_physid_direct(S, u, &physID, &len)) {
	    physID = (char *) "";
	    len = 0;
	  }
	  src_str.SetString(physID, len, allocator);

	  if (-1 == stinger_mapping_physid_direct(S, v, &physID, &len)) {
	    physID = (char *) "";
	    len = 0;
	  }
	  dst_str.SetString(physID, len, allocator);
	  val.SetArray();
	  val.PushBack(src_str, allocator);
	  val.PushBack(dst_str, allocator);
	  if (get_etypes) {
	    char * etype_str_ptr = stinger_etype_names_lookup_name(S, STINGER_EDGE_TYPE);
	    etype_str.SetString(etype_str_ptr, strlen(etype_str_ptr), allocator);
	    val.PushBack(etype_str, allocator);
	  }
	  edges_str.PushBack(val, allocator);
	}
      }

    } STINGER_FORALL_EDGES_OF_VTX_END();
  } STINGER_FORALL_EDGES_OF_VTX_END();

  result.AddMember("vertices", vtx, allocator);
  if (strings) {
    result.AddMember("vertices_str", vtx_str, allocator);
  }

  if (get_vtypes) {
    result.AddMember("vtypes", vtypes, allocator);
    if (strings) {
      result.AddMember("vtypes_str", vtypes_str, allocator);
    }
  }

  result.AddMember("egonet", edges, allocator);
  if (strings) {
    result.AddMember("egonet_str", edges_str, allocator);
  }

  free(marks);

  return 0;
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPropAssembly.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkPropAssembly.h"
#include "vtkViewport.h"

// Construct object with no children.
vtkPropAssembly::vtkPropAssembly()
{
  this->Parts = vtkPropCollection::New();
}

vtkPropAssembly::~vtkPropAssembly()
{
  this->Parts->Delete();
  this->Parts = NULL;
}

// Add a part to the list of Parts.
void vtkPropAssembly::AddPart(vtkProp *prop)
{
  if ( ! this->Parts->IsItemPresent(prop) )
    {
    this->Parts->AddItem(prop);
    this->Modified();
    }
}

// Remove a part from the list of parts,
void vtkPropAssembly::RemovePart(vtkProp *prop)
{
  if ( this->Parts->IsItemPresent(prop) )
    {
    this->Parts->RemoveItem(prop);
    this->Modified();
    }
}

// Get the list of parts for this prop assembly.
vtkPropCollection *vtkPropAssembly::GetParts()
{
  return this->Parts;
}

// Render this assembly and all of its Parts. The rendering process is recursive.
int vtkPropAssembly::RenderTranslucentGeometry(vtkViewport *ren)
{
  vtkProp *part;
  int   renderedSomething=0;

  // render the Paths
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      renderedSomething |= part->RenderTranslucentGeometry(ren);
      }
    }

  return renderedSomething;
}

// Render this assembly and all its parts. The rendering process is recursive.
int vtkPropAssembly::RenderOpaqueGeometry(vtkViewport *ren)
{
  vtkProp *part;
  int   renderedSomething=0;

  // render the Paths
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      renderedSomething |= part->RenderOpaqueGeometry(ren);
      }
    }

  return renderedSomething;
}

// Render this assembly and all its parts. The rendering process is recursive.
int vtkPropAssembly::RenderOverlay(vtkViewport *ren)
{
  vtkProp *part;
  int   renderedSomething=0;

  // render the Paths
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      renderedSomething |= part->RenderOverlay(ren);
      }
    }

  return renderedSomething;
}

// Render this assembly and all its parts. The rendering process is recursive.
int vtkPropAssembly::InitializeRayCasting(vtkViewport *ren)
{
  vtkProp *part;
  int needsToCast=0;

  // render the Paths
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      needsToCast |= part->InitializeRayCasting(ren);
      }
    }

  return needsToCast;
}

int vtkPropAssembly::CastViewRay(VTKRayCastRayInfo *ray)
{
  vtkProp *part;
  int rayHit=0;

  // render the Paths
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      rayHit |= part->CastViewRay(ray);
      }
    }

  return rayHit;
}

int vtkPropAssembly::RenderIntoImage(vtkViewport *ren)
{
  vtkProp *part;
  int success=0;

  // render the Paths
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      success |= part->RenderIntoImage(ren);
      }
    }

  return success;
}

void vtkPropAssembly::ReleaseGraphicsResources(vtkWindow *renWin)
{
  vtkProp *part;

  vtkProp::ReleaseGraphicsResources(renWin);

  // broadcast the message down the Parts
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    part->ReleaseGraphicsResources(renWin);
    }
}

// Get the bounds for the assembly as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
float *vtkPropAssembly::GetBounds()
{
  vtkProp *part;
  int i, n;
  float *bounds, bbox[24];
  int partVisible=0;

  this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = VTK_LARGE_FLOAT;
  this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = -VTK_LARGE_FLOAT;

  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      partVisible = 1;
      bounds = part->GetBounds();

      if ( bounds != NULL )
        {
        // fill out vertices of a bounding box
        bbox[ 0] = bounds[1]; bbox[ 1] = bounds[3]; bbox[ 2] = bounds[5];
        bbox[ 3] = bounds[1]; bbox[ 4] = bounds[2]; bbox[ 5] = bounds[5];
        bbox[ 6] = bounds[0]; bbox[ 7] = bounds[2]; bbox[ 8] = bounds[5];
        bbox[ 9] = bounds[0]; bbox[10] = bounds[3]; bbox[11] = bounds[5];
        bbox[12] = bounds[1]; bbox[13] = bounds[3]; bbox[14] = bounds[4];
        bbox[15] = bounds[1]; bbox[16] = bounds[2]; bbox[17] = bounds[4];
        bbox[18] = bounds[0]; bbox[19] = bounds[2]; bbox[20] = bounds[4];
        bbox[21] = bounds[0]; bbox[22] = bounds[3]; bbox[23] = bounds[4];

        for (i = 0; i < 8; i++)
          {
          for (n = 0; n < 3; n++)
            {
            if (bbox[i*3+n] < this->Bounds[n*2])
              {
              this->Bounds[n*2] = bbox[i*3+n];
              }
            if (bbox[i*3+n] > this->Bounds[n*2+1])
              {
              this->Bounds[n*2+1] = bbox[i*3+n];
              }
            }
          }//for each point of box
        }//if bounds
      }//for each part
    }//for each part

  if ( ! partVisible )
    {
    return NULL;
    }
  else
    {
    return this->Bounds;
    }
}

unsigned long int vtkPropAssembly::GetMTime()
{
  unsigned long mTime=this->vtkProp::GetMTime();
  unsigned long time;
  vtkProp *part;

  for (this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    time = part->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }

  return mTime;
}

void vtkPropAssembly::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkProp::PrintSelf(os,indent);

  os << indent << "There are: " << this->Parts->GetNumberOfItems()
     << " parts in this assembly\n";
}
<commit_msg>ENH:Compute allocated render time more accurately<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPropAssembly.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkPropAssembly.h"
#include "vtkViewport.h"

// Construct object with no children.
vtkPropAssembly::vtkPropAssembly()
{
  this->Parts = vtkPropCollection::New();
}

vtkPropAssembly::~vtkPropAssembly()
{
  this->Parts->Delete();
  this->Parts = NULL;
}

// Add a part to the list of Parts.
void vtkPropAssembly::AddPart(vtkProp *prop)
{
  if ( ! this->Parts->IsItemPresent(prop) )
    {
    this->Parts->AddItem(prop);
    this->Modified();
    }
}

// Remove a part from the list of parts,
void vtkPropAssembly::RemovePart(vtkProp *prop)
{
  if ( this->Parts->IsItemPresent(prop) )
    {
    this->Parts->RemoveItem(prop);
    this->Modified();
    }
}

// Get the list of parts for this prop assembly.
vtkPropCollection *vtkPropAssembly::GetParts()
{
  return this->Parts;
}

// Render this assembly and all of its Parts. The rendering process is recursive.
int vtkPropAssembly::RenderTranslucentGeometry(vtkViewport *ren)
{
  vtkProp *part;
  float fraction;
  int renderedSomething=0;

  fraction = this->AllocatedRenderTime /
             (float)this->Parts->GetNumberOfItems();

  // render the Paths
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      part->SetAllocatedRenderTime(fraction);
      renderedSomething |= part->RenderTranslucentGeometry(ren);
      }
    }

  return renderedSomething;
}

// Render this assembly and all its parts. The rendering process is recursive.
int vtkPropAssembly::RenderOpaqueGeometry(vtkViewport *ren)
{
  vtkProp *part;
  float fraction;
  int   renderedSomething=0;

  fraction = this->AllocatedRenderTime /
             (float)this->Parts->GetNumberOfItems();

  // render the Paths
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      part->SetAllocatedRenderTime(fraction);
      renderedSomething |= part->RenderOpaqueGeometry(ren);
      }
    }

  return renderedSomething;
}

// Render this assembly and all its parts. The rendering process is recursive.
int vtkPropAssembly::RenderOverlay(vtkViewport *ren)
{
  vtkProp *part;
  float fraction;
  int   renderedSomething=0;

  fraction = this->AllocatedRenderTime /
             (float)this->Parts->GetNumberOfItems();

  // render the Paths
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      part->SetAllocatedRenderTime(fraction);
      renderedSomething |= part->RenderOverlay(ren);
      }
    }

  return renderedSomething;
}

// Render this assembly and all its parts. The rendering process is recursive.
int vtkPropAssembly::InitializeRayCasting(vtkViewport *ren)
{
  vtkProp *part;
  int needsToCast=0;

  // render the Paths
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      needsToCast |= part->InitializeRayCasting(ren);
      }
    }

  return needsToCast;
}

int vtkPropAssembly::CastViewRay(VTKRayCastRayInfo *ray)
{
  vtkProp *part;
  int rayHit=0;

  // render the Paths
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      rayHit |= part->CastViewRay(ray);
      }
    }

  return rayHit;
}

int vtkPropAssembly::RenderIntoImage(vtkViewport *ren)
{
  vtkProp *part;
  int success=0;

  // render the Paths
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      success |= part->RenderIntoImage(ren);
      }
    }

  return success;
}

void vtkPropAssembly::ReleaseGraphicsResources(vtkWindow *renWin)
{
  vtkProp *part;

  vtkProp::ReleaseGraphicsResources(renWin);

  // broadcast the message down the Parts
  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    part->ReleaseGraphicsResources(renWin);
    }
}

// Get the bounds for the assembly as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
float *vtkPropAssembly::GetBounds()
{
  vtkProp *part;
  int i, n;
  float *bounds, bbox[24];
  int partVisible=0;

  this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = VTK_LARGE_FLOAT;
  this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = -VTK_LARGE_FLOAT;

  for ( this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    if ( part->GetVisibility() )
      {
      bounds = part->GetBounds();

      if ( bounds != NULL )
        {
        //  For the purposes of GetBounds, an object is visisble only if
        //  its visibility is on and it has visible parts.
        partVisible = 1;

        // fill out vertices of a bounding box
        bbox[ 0] = bounds[1]; bbox[ 1] = bounds[3]; bbox[ 2] = bounds[5];
        bbox[ 3] = bounds[1]; bbox[ 4] = bounds[2]; bbox[ 5] = bounds[5];
        bbox[ 6] = bounds[0]; bbox[ 7] = bounds[2]; bbox[ 8] = bounds[5];
        bbox[ 9] = bounds[0]; bbox[10] = bounds[3]; bbox[11] = bounds[5];
        bbox[12] = bounds[1]; bbox[13] = bounds[3]; bbox[14] = bounds[4];
        bbox[15] = bounds[1]; bbox[16] = bounds[2]; bbox[17] = bounds[4];
        bbox[18] = bounds[0]; bbox[19] = bounds[2]; bbox[20] = bounds[4];
        bbox[21] = bounds[0]; bbox[22] = bounds[3]; bbox[23] = bounds[4];

        for (i = 0; i < 8; i++)
          {
          for (n = 0; n < 3; n++)
            {
            if (bbox[i*3+n] < this->Bounds[n*2])
              {
              this->Bounds[n*2] = bbox[i*3+n];
              }
            if (bbox[i*3+n] > this->Bounds[n*2+1])
              {
              this->Bounds[n*2+1] = bbox[i*3+n];
              }
            }
          }//for each point of box
        }//if bounds
      }//for each part
    }//for each part

  if ( ! partVisible )
    {
    return NULL;
    }
  else
    {
    return this->Bounds;
    }
}

unsigned long int vtkPropAssembly::GetMTime()
{
  unsigned long mTime=this->vtkProp::GetMTime();
  unsigned long time;
  vtkProp *part;

  for (this->Parts->InitTraversal(); (part=this->Parts->GetNextProp()); )
    {
    time = part->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }

  return mTime;
}

void vtkPropAssembly::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkProp::PrintSelf(os,indent);

  os << indent << "There are: " << this->Parts->GetNumberOfItems()
     << " parts in this assembly\n";
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2019 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>

#include <arpa/inet.h>
#include <fcntl.h>
#include <gflags/gflags.h>
#include <inttypes.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/wait.h>
#include <unistd.h>
#include <chrono>
#include <cstdlib>
#include <memory>
#include <string>
#include <thread>

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/support/channel_arguments.h>

#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/socket_mutator.h"
#include "src/proto/grpc/testing/empty.pb.h"
#include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
#include "src/proto/grpc/testing/test.pb.h"

#include "test/cpp/util/test_config.h"
#include "test/cpp/util/test_credentials_provider.h"

DEFINE_string(custom_credentials_type, "", "User provided credentials type.");
DEFINE_string(server_uri, "localhost:1000", "Server URI target");
DEFINE_string(unroute_lb_and_backend_addrs_cmd, "exit 1",
              "Shell command used to make LB and backend addresses unroutable");
DEFINE_string(blackhole_lb_and_backend_addrs_cmd, "exit 1",
              "Shell command used to make LB and backend addresses blackholed");
DEFINE_string(
    test_case, "",
    "Test case to run. Valid options are:\n\n"
    "fast_fallback_before_startup : fallback before establishing connection to "
    "LB;\n"
    "fast_fallback_after_startup : fallback after startup due to LB/backend "
    "addresses becoming unroutable;\n"
    "slow_fallback_before_startup : fallback before startup due to LB address "
    "being blackholed;\n"
    "slow_fallback_after_startup : fallback after startup due to LB/backend "
    "addresses becoming blackholed;\n");

using grpc::testing::GrpclbRouteType;
using grpc::testing::SimpleRequest;
using grpc::testing::SimpleResponse;
using grpc::testing::TestService;

namespace {

enum RpcMode {
  FailFast,
  WaitForReady,
};

GrpclbRouteType DoRPCAndGetPath(TestService::Stub* stub, int deadline_seconds,
                                RpcMode rpc_mode) {
  gpr_log(GPR_INFO, "DoRPCAndGetPath deadline_seconds:%d rpc_mode:%d",
          deadline_seconds, rpc_mode);
  SimpleRequest request;
  SimpleResponse response;
  grpc::ClientContext context;
  if (rpc_mode == WaitForReady) {
    context.set_wait_for_ready(true);
  }
  request.set_fill_grpclb_route_type(true);
  std::chrono::system_clock::time_point deadline =
      std::chrono::system_clock::now() + std::chrono::seconds(deadline_seconds);
  context.set_deadline(deadline);
  grpc::Status s = stub->UnaryCall(&context, request, &response);
  if (!s.ok()) {
    gpr_log(GPR_INFO, "DoRPCAndGetPath failed. status-message: %s",
            s.error_message().c_str());
    return GrpclbRouteType::GRPCLB_ROUTE_TYPE_UNKNOWN;
  }
  GPR_ASSERT(response.grpclb_route_type() ==
                 GrpclbRouteType::GRPCLB_ROUTE_TYPE_BACKEND ||
             response.grpclb_route_type() ==
                 GrpclbRouteType::GRPCLB_ROUTE_TYPE_FALLBACK);
  gpr_log(GPR_INFO, "DoRPCAndGetPath done. grpclb_route_type:%d",
          response.grpclb_route_type());
  return response.grpclb_route_type();
}

GrpclbRouteType DoRPCAndGetPath(TestService::Stub* stub, int deadline_seconds) {
  return DoRPCAndGetPath(stub, deadline_seconds, FailFast);
}

GrpclbRouteType DoWaitForReadyRPCAndGetPath(TestService::Stub* stub,
                                            int deadline_seconds) {
  return DoRPCAndGetPath(stub, deadline_seconds, WaitForReady);
}

bool TcpUserTimeoutMutateFd(int fd, grpc_socket_mutator* mutator) {
  int timeout = 20000;  // 20 seconds
  gpr_log(GPR_INFO, "Setting socket option TCP_USER_TIMEOUT on fd: %d", fd);
  if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout,
                      sizeof(timeout))) {
    gpr_log(GPR_ERROR, "Failed to set socket option TCP_USER_TIMEOUT");
    abort();
  }
  int newval;
  socklen_t len = sizeof(newval);
  if (0 != getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len) ||
      newval != timeout) {
    gpr_log(GPR_ERROR, "Failed to get expected socket option TCP_USER_TIMEOUT");
    abort();
  }
  return true;
}

int TcpUserTimeoutCompare(grpc_socket_mutator* a, grpc_socket_mutator* b) {
  return 0;
}

void TcpUserTimeoutDestroy(grpc_socket_mutator* mutator) { gpr_free(mutator); }

const grpc_socket_mutator_vtable kTcpUserTimeoutMutatorVtable =
    grpc_socket_mutator_vtable{
        .mutate_fd = TcpUserTimeoutMutateFd,
        .compare = TcpUserTimeoutCompare,
        .destroy = TcpUserTimeoutDestroy,
    };

std::unique_ptr<TestService::Stub> CreateFallbackTestStub() {
  grpc::ChannelArguments channel_args;
  grpc_socket_mutator* tcp_user_timeout_mutator =
      static_cast<grpc_socket_mutator*>(
          gpr_malloc(sizeof(tcp_user_timeout_mutator)));
  grpc_socket_mutator_init(tcp_user_timeout_mutator,
                           &kTcpUserTimeoutMutatorVtable);
  channel_args.SetSocketMutator(tcp_user_timeout_mutator);
  // Allow LB policy to be configured by service config
  channel_args.SetInt(GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION, 0);
  std::shared_ptr<grpc::ChannelCredentials> channel_creds =
      grpc::testing::GetCredentialsProvider()->GetChannelCredentials(
          FLAGS_custom_credentials_type, &channel_args);
  return TestService::NewStub(
      grpc::CreateCustomChannel(FLAGS_server_uri, channel_creds, channel_args));
}

void RunCommand(const std::string& command) {
  gpr_log(GPR_INFO, "RunCommand: |%s|", command.c_str());
  int out = std::system(command.c_str());
  if (WIFEXITED(out)) {
    int code = WEXITSTATUS(out);
    if (code != 0) {
      gpr_log(GPR_ERROR, "RunCommand failed exit code:%d command:|%s|", code,
              command.c_str());
      abort();
    }
  } else {
    gpr_log(GPR_ERROR, "RunCommand failed command:|%s|", command.c_str());
    abort();
  }
}

void RunFallbackBeforeStartupTest(
    const std::string& break_lb_and_backend_conns_cmd,
    int per_rpc_deadline_seconds) {
  std::unique_ptr<TestService::Stub> stub = CreateFallbackTestStub();
  RunCommand(break_lb_and_backend_conns_cmd);
  for (size_t i = 0; i < 30; i++) {
    GrpclbRouteType grpclb_route_type =
        DoRPCAndGetPath(stub.get(), per_rpc_deadline_seconds);
    if (grpclb_route_type != GrpclbRouteType::GRPCLB_ROUTE_TYPE_FALLBACK) {
      gpr_log(GPR_ERROR, "Expected grpclb route type: FALLBACK. Got: %d",
              grpclb_route_type);
      abort();
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
}

void DoFastFallbackBeforeStartup() {
  RunFallbackBeforeStartupTest(FLAGS_unroute_lb_and_backend_addrs_cmd, 9);
}

void DoSlowFallbackBeforeStartup() {
  RunFallbackBeforeStartupTest(FLAGS_blackhole_lb_and_backend_addrs_cmd, 20);
}

void RunFallbackAfterStartupTest(
    const std::string& break_lb_and_backend_conns_cmd) {
  std::unique_ptr<TestService::Stub> stub = CreateFallbackTestStub();
  GrpclbRouteType grpclb_route_type = DoRPCAndGetPath(stub.get(), 20);
  if (grpclb_route_type != GrpclbRouteType::GRPCLB_ROUTE_TYPE_BACKEND) {
    gpr_log(GPR_ERROR, "Expected grpclb route type: BACKEND. Got: %d",
            grpclb_route_type);
    abort();
  }
  RunCommand(break_lb_and_backend_conns_cmd);
  for (size_t i = 0; i < 40; i++) {
    GrpclbRouteType grpclb_route_type =
        DoWaitForReadyRPCAndGetPath(stub.get(), 1);
    // Backends should be unreachable by now, otherwise the test is broken.
    GPR_ASSERT(grpclb_route_type != GrpclbRouteType::GRPCLB_ROUTE_TYPE_BACKEND);
    if (grpclb_route_type == GrpclbRouteType::GRPCLB_ROUTE_TYPE_FALLBACK) {
      gpr_log(GPR_INFO,
              "Made one successul RPC to a fallback. Now expect the same for "
              "the rest.");
      break;
    } else {
      gpr_log(GPR_ERROR, "Retryable RPC failure on iteration: %" PRIdPTR, i);
    }
  }
  for (size_t i = 0; i < 30; i++) {
    GrpclbRouteType grpclb_route_type = DoRPCAndGetPath(stub.get(), 20);
    if (grpclb_route_type != GrpclbRouteType::GRPCLB_ROUTE_TYPE_FALLBACK) {
      gpr_log(GPR_ERROR, "Expected grpclb route type: FALLBACK. Got: %d",
              grpclb_route_type);
      abort();
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
}

void DoFastFallbackAfterStartup() {
  RunFallbackAfterStartupTest(FLAGS_unroute_lb_and_backend_addrs_cmd);
}

void DoSlowFallbackAfterStartup() {
  RunFallbackAfterStartupTest(FLAGS_blackhole_lb_and_backend_addrs_cmd);
}
}  // namespace

int main(int argc, char** argv) {
  grpc::testing::InitTest(&argc, &argv, true);
  gpr_log(GPR_INFO, "Testing: %s", FLAGS_test_case.c_str());
  if (FLAGS_test_case == "fast_fallback_before_startup") {
    DoFastFallbackBeforeStartup();
    gpr_log(GPR_INFO, "DoFastFallbackBeforeStartup done!");
  } else if (FLAGS_test_case == "slow_fallback_before_startup") {
    DoSlowFallbackBeforeStartup();
    gpr_log(GPR_INFO, "DoSlowFallbackBeforeStartup done!");
  } else if (FLAGS_test_case == "fast_fallback_after_startup") {
    DoFastFallbackAfterStartup();
    gpr_log(GPR_INFO, "DoFastFallbackAfterStartup done!");
  } else if (FLAGS_test_case == "slow_fallback_after_startup") {
    DoSlowFallbackAfterStartup();
    gpr_log(GPR_INFO, "DoSlowFallbackAfterStartup done!");
  } else {
    gpr_log(GPR_ERROR, "Invalid test case: %s", FLAGS_test_case.c_str());
    abort();
  }
}
<commit_msg>Fix fallback test breaking on mac bazel<commit_after>/*
 *
 * Copyright 2019 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>

#include "src/core/lib/iomgr/port.h"

#include <arpa/inet.h>
#include <fcntl.h>
#include <gflags/gflags.h>
#include <inttypes.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/wait.h>
#include <unistd.h>
#include <chrono>
#include <cstdlib>
#include <memory>
#include <string>
#include <thread>

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/support/channel_arguments.h>

#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/socket_mutator.h"
#include "src/proto/grpc/testing/empty.pb.h"
#include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
#include "src/proto/grpc/testing/test.pb.h"

#include "test/cpp/util/test_config.h"
#include "test/cpp/util/test_credentials_provider.h"

DEFINE_string(custom_credentials_type, "", "User provided credentials type.");
DEFINE_string(server_uri, "localhost:1000", "Server URI target");
DEFINE_string(unroute_lb_and_backend_addrs_cmd, "exit 1",
              "Shell command used to make LB and backend addresses unroutable");
DEFINE_string(blackhole_lb_and_backend_addrs_cmd, "exit 1",
              "Shell command used to make LB and backend addresses blackholed");
DEFINE_string(
    test_case, "",
    "Test case to run. Valid options are:\n\n"
    "fast_fallback_before_startup : fallback before establishing connection to "
    "LB;\n"
    "fast_fallback_after_startup : fallback after startup due to LB/backend "
    "addresses becoming unroutable;\n"
    "slow_fallback_before_startup : fallback before startup due to LB address "
    "being blackholed;\n"
    "slow_fallback_after_startup : fallback after startup due to LB/backend "
    "addresses becoming blackholed;\n");

#ifdef GRPC_HAVE_TCP_USER_TIMEOUT
using grpc::testing::GrpclbRouteType;
using grpc::testing::SimpleRequest;
using grpc::testing::SimpleResponse;
using grpc::testing::TestService;

namespace {

enum RpcMode {
  FailFast,
  WaitForReady,
};

GrpclbRouteType DoRPCAndGetPath(TestService::Stub* stub, int deadline_seconds,
                                RpcMode rpc_mode) {
  gpr_log(GPR_INFO, "DoRPCAndGetPath deadline_seconds:%d rpc_mode:%d",
          deadline_seconds, rpc_mode);
  SimpleRequest request;
  SimpleResponse response;
  grpc::ClientContext context;
  if (rpc_mode == WaitForReady) {
    context.set_wait_for_ready(true);
  }
  request.set_fill_grpclb_route_type(true);
  std::chrono::system_clock::time_point deadline =
      std::chrono::system_clock::now() + std::chrono::seconds(deadline_seconds);
  context.set_deadline(deadline);
  grpc::Status s = stub->UnaryCall(&context, request, &response);
  if (!s.ok()) {
    gpr_log(GPR_INFO, "DoRPCAndGetPath failed. status-message: %s",
            s.error_message().c_str());
    return GrpclbRouteType::GRPCLB_ROUTE_TYPE_UNKNOWN;
  }
  GPR_ASSERT(response.grpclb_route_type() ==
                 GrpclbRouteType::GRPCLB_ROUTE_TYPE_BACKEND ||
             response.grpclb_route_type() ==
                 GrpclbRouteType::GRPCLB_ROUTE_TYPE_FALLBACK);
  gpr_log(GPR_INFO, "DoRPCAndGetPath done. grpclb_route_type:%d",
          response.grpclb_route_type());
  return response.grpclb_route_type();
}

GrpclbRouteType DoRPCAndGetPath(TestService::Stub* stub, int deadline_seconds) {
  return DoRPCAndGetPath(stub, deadline_seconds, FailFast);
}

GrpclbRouteType DoWaitForReadyRPCAndGetPath(TestService::Stub* stub,
                                            int deadline_seconds) {
  return DoRPCAndGetPath(stub, deadline_seconds, WaitForReady);
}

bool TcpUserTimeoutMutateFd(int fd, grpc_socket_mutator* mutator) {
  int timeout = 20000;  // 20 seconds
  gpr_log(GPR_INFO, "Setting socket option TCP_USER_TIMEOUT on fd: %d", fd);
  if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout,
                      sizeof(timeout))) {
    gpr_log(GPR_ERROR, "Failed to set socket option TCP_USER_TIMEOUT");
    abort();
  }
  int newval;
  socklen_t len = sizeof(newval);
  if (0 != getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len) ||
      newval != timeout) {
    gpr_log(GPR_ERROR, "Failed to get expected socket option TCP_USER_TIMEOUT");
    abort();
  }
  return true;
}

int TcpUserTimeoutCompare(grpc_socket_mutator* a, grpc_socket_mutator* b) {
  return 0;
}

void TcpUserTimeoutDestroy(grpc_socket_mutator* mutator) { gpr_free(mutator); }

const grpc_socket_mutator_vtable kTcpUserTimeoutMutatorVtable =
    grpc_socket_mutator_vtable{
        .mutate_fd = TcpUserTimeoutMutateFd,
        .compare = TcpUserTimeoutCompare,
        .destroy = TcpUserTimeoutDestroy,
    };

std::unique_ptr<TestService::Stub> CreateFallbackTestStub() {
  grpc::ChannelArguments channel_args;
  grpc_socket_mutator* tcp_user_timeout_mutator =
      static_cast<grpc_socket_mutator*>(
          gpr_malloc(sizeof(tcp_user_timeout_mutator)));
  grpc_socket_mutator_init(tcp_user_timeout_mutator,
                           &kTcpUserTimeoutMutatorVtable);
  channel_args.SetSocketMutator(tcp_user_timeout_mutator);
  // Allow LB policy to be configured by service config
  channel_args.SetInt(GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION, 0);
  std::shared_ptr<grpc::ChannelCredentials> channel_creds =
      grpc::testing::GetCredentialsProvider()->GetChannelCredentials(
          FLAGS_custom_credentials_type, &channel_args);
  return TestService::NewStub(
      grpc::CreateCustomChannel(FLAGS_server_uri, channel_creds, channel_args));
}

void RunCommand(const std::string& command) {
  gpr_log(GPR_INFO, "RunCommand: |%s|", command.c_str());
  int out = std::system(command.c_str());
  if (WIFEXITED(out)) {
    int code = WEXITSTATUS(out);
    if (code != 0) {
      gpr_log(GPR_ERROR, "RunCommand failed exit code:%d command:|%s|", code,
              command.c_str());
      abort();
    }
  } else {
    gpr_log(GPR_ERROR, "RunCommand failed command:|%s|", command.c_str());
    abort();
  }
}

void RunFallbackBeforeStartupTest(
    const std::string& break_lb_and_backend_conns_cmd,
    int per_rpc_deadline_seconds) {
  std::unique_ptr<TestService::Stub> stub = CreateFallbackTestStub();
  RunCommand(break_lb_and_backend_conns_cmd);
  for (size_t i = 0; i < 30; i++) {
    GrpclbRouteType grpclb_route_type =
        DoRPCAndGetPath(stub.get(), per_rpc_deadline_seconds);
    if (grpclb_route_type != GrpclbRouteType::GRPCLB_ROUTE_TYPE_FALLBACK) {
      gpr_log(GPR_ERROR, "Expected grpclb route type: FALLBACK. Got: %d",
              grpclb_route_type);
      abort();
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
}

void DoFastFallbackBeforeStartup() {
  RunFallbackBeforeStartupTest(FLAGS_unroute_lb_and_backend_addrs_cmd, 9);
}

void DoSlowFallbackBeforeStartup() {
  RunFallbackBeforeStartupTest(FLAGS_blackhole_lb_and_backend_addrs_cmd, 20);
}

void RunFallbackAfterStartupTest(
    const std::string& break_lb_and_backend_conns_cmd) {
  std::unique_ptr<TestService::Stub> stub = CreateFallbackTestStub();
  GrpclbRouteType grpclb_route_type = DoRPCAndGetPath(stub.get(), 20);
  if (grpclb_route_type != GrpclbRouteType::GRPCLB_ROUTE_TYPE_BACKEND) {
    gpr_log(GPR_ERROR, "Expected grpclb route type: BACKEND. Got: %d",
            grpclb_route_type);
    abort();
  }
  RunCommand(break_lb_and_backend_conns_cmd);
  for (size_t i = 0; i < 40; i++) {
    GrpclbRouteType grpclb_route_type =
        DoWaitForReadyRPCAndGetPath(stub.get(), 1);
    // Backends should be unreachable by now, otherwise the test is broken.
    GPR_ASSERT(grpclb_route_type != GrpclbRouteType::GRPCLB_ROUTE_TYPE_BACKEND);
    if (grpclb_route_type == GrpclbRouteType::GRPCLB_ROUTE_TYPE_FALLBACK) {
      gpr_log(GPR_INFO,
              "Made one successul RPC to a fallback. Now expect the same for "
              "the rest.");
      break;
    } else {
      gpr_log(GPR_ERROR, "Retryable RPC failure on iteration: %" PRIdPTR, i);
    }
  }
  for (size_t i = 0; i < 30; i++) {
    GrpclbRouteType grpclb_route_type = DoRPCAndGetPath(stub.get(), 20);
    if (grpclb_route_type != GrpclbRouteType::GRPCLB_ROUTE_TYPE_FALLBACK) {
      gpr_log(GPR_ERROR, "Expected grpclb route type: FALLBACK. Got: %d",
              grpclb_route_type);
      abort();
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
}

void DoFastFallbackAfterStartup() {
  RunFallbackAfterStartupTest(FLAGS_unroute_lb_and_backend_addrs_cmd);
}

void DoSlowFallbackAfterStartup() {
  RunFallbackAfterStartupTest(FLAGS_blackhole_lb_and_backend_addrs_cmd);
}
}  // namespace

int main(int argc, char** argv) {
  grpc::testing::InitTest(&argc, &argv, true);
  gpr_log(GPR_INFO, "Testing: %s", FLAGS_test_case.c_str());
  if (FLAGS_test_case == "fast_fallback_before_startup") {
    DoFastFallbackBeforeStartup();
    gpr_log(GPR_INFO, "DoFastFallbackBeforeStartup done!");
  } else if (FLAGS_test_case == "slow_fallback_before_startup") {
    DoSlowFallbackBeforeStartup();
    gpr_log(GPR_INFO, "DoSlowFallbackBeforeStartup done!");
  } else if (FLAGS_test_case == "fast_fallback_after_startup") {
    DoFastFallbackAfterStartup();
    gpr_log(GPR_INFO, "DoFastFallbackAfterStartup done!");
  } else if (FLAGS_test_case == "slow_fallback_after_startup") {
    DoSlowFallbackAfterStartup();
    gpr_log(GPR_INFO, "DoSlowFallbackAfterStartup done!");
  } else {
    gpr_log(GPR_ERROR, "Invalid test case: %s", FLAGS_test_case.c_str());
    abort();
  }
}
#else
int main(int argc, char** argv) {
  grpc::testing::InitTest(&argc, &argv, true);
  gpr_log(GPR_ERROR,
          "This test requires TCP_USER_TIMEOUT, which isn't available");
  abort();
}
#endif  // GRPC_HAVE_TCP_USER_TIMEOUT
<|endoftext|>


<commit_before>/*
 * ofxAxisGrabber.cpp
 *
 *  Created on: Sep 23, 2012
 *      Author: arturo
 */

#include "ofxAxisGrabber.h"
#include "Poco/DOM/DOMParser.h"
#include "Poco/DOM/Document.h"
#include "Poco/DOM/NodeList.h"
#include "Poco/DOM/NamedNodeMap.h"
#include "ofAppRunner.h"

ofxAxisGrabber::ofxAxisGrabber() {
	paramRefreshRateMs = 0;
	desiredFramerate = 0;
	startTimeOneSecMicros = 0;
	framesInOneSec = 0;
	codec = H264;
	updating = false;
	started = false;

	parameters.add(focus.set("focus",100,0,297));
	parameters.add(manualIris.set("manualIris",true));
	parameters.add(exposure.set("exposure",50,0,100));
	parameters.add(irFilterCut.set("irFilterCut",0,0,2));
	parameters.add(compression.set("compression",30,0,100));
	parameters.add(fps.set("fps",0,0,60));
	parameters.add(cameraConnected.set("cameraConnected",false));
	parameters.add(cameraAuth.set("cameraAuth",false));
	prevFocus = focus;

	compression.addListener(this,&ofxAxisGrabber::compressionChanged);
	exposure.addListener(this,&ofxAxisGrabber::exposureChanged);
	irFilterCut.addListener(this,&ofxAxisGrabber::irFilterCutChanged);
	manualIris.addListener(this,&ofxAxisGrabber::setManualIris);
	focus.addListener(this,&ofxAxisGrabber::focusChanged);
}

//overwritten from ofBaseVideoGrabber
void ofxAxisGrabber::listDevices(){

}

void ofxAxisGrabber::setCodec(ofxAxisGrabber::AxisCodec _codec){
	codec = _codec;
}

void ofxAxisGrabber::setCameraAddress(string address){
	string parametersName = address;
	ofStringReplace(parametersName,".","_");
	parameters.setName(parametersName);
	cameraAddress = address;
}

string ofxAxisGrabber::getCameraAddress(){
	return cameraAddress;
}

void ofxAxisGrabber::setCompression(int _compression){
	compression = _compression;
}

bool ofxAxisGrabber::initGrabber(int w, int h){
	startTimeOneSecMicros = 0;
	framesInOneSec=0;
	fps=0;

	if(cameraAddress==""){
		ofLogError() << "cannot init axis grabber, must call setCameraAddress before initGrabber" << endl;
	}

	string codecStr = codec==MJPG?"mjpg":"h264";
	stringstream url;
	url << "rtsp://" << cameraAddress <<
			"/axis-media/media.amp?"
			"videocodec=" << codecStr <<
			"&resolution=" << w << "x" << h <<
			"&compression=" << compression <<
			"&mirror=0"
			"&rotation=180"
			"&textposition=top"
			"&textbackgroundcolor=black"
			"&textcolor=white"
			"&text=0"
			"&clock=0"
			"&date=0"
			"&overlayimage=0"
			"&fps=" << desiredFramerate <<
			"&audio=0"
			"&keyframe_interval=8"
			"&videobitrate=0"
			"&maxframesize=0";

	stringstream pipeline;
	pipeline << "rtspsrc location=\"" << url.str() << "\" latency=0 ! decodebin2 ! ffmpegcolorspace ! queue ";

	ofLogNotice("ofxAxisGrabber") << "pipeline: ";
	ofLogNotice("ofxAxisGrabber") << pipeline.str();
	bool ret = gst.setPipeline(pipeline.str(),24,true,w,h);

	//gst.loadMovie("http://10.42.0.23/axis-cgi/mjpg/video.cgi?fps=30&nbrofframes=0&resolution=640x480");
	//gst.loadMovie("rtsp://10.42.0.23:554/axis-media/media.amp?videocodec=h264");
	//player.loadMovie("rtsp://10.42.0.23:554/axis-media/media.amp?videocodec=h264&resolution="+ofToString(w)+"x"+ofToString(h)+"&compression=10&mirror=0&rotation=180&textposition=top&textbackgroundcolor=black&textcolor=white&text=0&clock=0&date=0&overlayimage=0&fps=0&audio=0&keyframe_interval=32&videobitrate=0&maxframesize=0");
	cameraConnected = ret;
	if(ret) {
		gst.play();

		http.setTimeoutSeconds(30);
		http.start();
		if(!getPocoThread().isRunning()) startThread();
	}else{
		ofLogError("ofxAxisGrabber") << "couldn't allocate gstreamer";
	}

	started = ret;
	return ret;
}

void ofxAxisGrabber::newResponse(ofxHttpResponse & response){
	if(response.status==-1){
		cameraConnected = false;
		http.clearQueue();
	}
}

void ofxAxisGrabber::focusChanged(int & focus){
	if(updating || cameraAddress=="") return;
	float step = float(focus - prevFocus)/297.;
	http.addUrl("http://"+cameraAddress+"/axis-cgi/opticssetup.cgi?rfocus="+ofToString(step)+"&timestamp="+ofToString(ofGetSystemTime()));
	prevFocus = focus;
}

string ofxAxisGrabber::getStrPropertyValue(string property){
	if(cameraAddress=="") return "";
	ofxHttpResponse response = http.getUrl("http://"+cameraAddress+"/axis-cgi/param.cgi?action=list&group="+property+"&timestamp="+ofToString(ofGetSystemTime()));
	if(response.status==200){
		return string(response.responseBody).substr(string(property).size()+1);
	}else{
		return "";
	}
}

int ofxAxisGrabber::getIntPropertyValue(string property){
	if(cameraAddress=="") return 0;
	string strValue = getStrPropertyValue(property);
	if(strValue!=""){
		return ofToInt(strValue);
	}else{
		return 0;
	}
}

float ofxAxisGrabber::getFloatPropertyValue(string property){
	if(cameraAddress=="") return 0;
	string strValue = getStrPropertyValue(property);
	if(strValue!=""){
		return ofToFloat(strValue);
	}else{
		return 0;
	}
}

template<typename T>
void ofxAxisGrabber::setPropertyValue(string property, T & value){
	if(cameraAddress=="") return;
	http.addUrl("http://"+cameraAddress+"/axis-cgi/param.cgi?action=update&"+property+"="+ofToString(value)+"&timestamp="+ofToString(ofGetSystemTime()));
}

void ofxAxisGrabber::exposureChanged(int & exposure){
	if(!updating)
		setPropertyValue("ImageSource.I0.Sensor.ExposureValue",exposure);
}

void ofxAxisGrabber::checkExposure(){
	if(cameraAddress=="") return;
	exposure = getIntPropertyValue("ImageSource.I0.Sensor.ExposureValue");
}

void ofxAxisGrabber::irFilterCutChanged(int & irFilterCut){
	if(!updating){
		switch(irFilterCut){
		case 0:
			setPropertyValue("ImageSource.I0.DayNight.IrCutFilter","auto");
			break;
		case 1:
			setPropertyValue("ImageSource.I0.DayNight.IrCutFilter","yes");
			break;
		case 2:
			setPropertyValue("ImageSource.I0.DayNight.IrCutFilter","no");
			break;
		}
	}
}

void ofxAxisGrabber::checkIRFilterCut(){
	string strIRFilter = getStrPropertyValue("ImageSource.I0.DayNight.IrCutFilter");
	if(strIRFilter=="auto"){
		irFilterCut=0;
	}else if(strIRFilter=="yes"){
		irFilterCut=1;
	}if(strIRFilter=="no"){
		irFilterCut=2;
	}
}

void ofxAxisGrabber::compressionChanged(int & compression){
	if(!updating)
		setPropertyValue("Image.I0.Appearance.Compression",compression);
}

void ofxAxisGrabber::checkCompression(){
	compression = getIntPropertyValue("Image.I0.Appearance.Compression");
}

void ofxAxisGrabber::requestFocusWindow(){
	ofxHttpResponse response = http.getUrl("http://"+cameraAddress+"/axis-cgi/param.cgi?action=list&group=ImageSource.I0.Focus.Window.W0&timestamp="+ofToString(ofGetSystemTime()));
	if(response.status==200){
		string focusWindowStr = response.responseBody;
		focusWindowStr = focusWindowStr.substr(string("ImageSource.I0.Focus.Window.W0=").size());
		vector<string> coords = ofSplitString(focusWindowStr,":");

		focusWindow.x = ofToFloat(ofSplitString(coords[0],",")[0]);
		focusWindow.y = ofToFloat(ofSplitString(coords[0],",")[1]);
		focusWindow.width = -(ofToFloat(ofSplitString(coords[1],",")[0])-focusWindow.x);
		focusWindow.height = -(ofToFloat(ofSplitString(coords[2],",")[1])-focusWindow.y);
		focusWindow.y = 1-focusWindow.y;
		focusWindow.x = 1-focusWindow.x;

		focusWindowScaled = focusWindow;
		focusWindowScaled.x*=gst.getWidth();
		focusWindowScaled.y*=gst.getHeight();
		focusWindowScaled.width*=gst.getWidth();
		focusWindowScaled.height*=gst.getHeight();
	}
}

void ofxAxisGrabber::setManualIris(bool & manual){
	http.addUrl("http://"+cameraAddress+"//axis-cgi/irissetup.cgi?automatic=" + string(manual?"no":"yes") + "&timestamp="+ofToString(ofGetSystemTime()));
}

ofRectangle & ofxAxisGrabber::getFocusWindow(){
	return focusWindowScaled;
}

void ofxAxisGrabber::setFocusWindow(const ofRectangle & focusWindow){
	focusWindowScaled = focusWindow;
	setFocusWindow();
}

void ofxAxisGrabber::setFocusWindow(){
	if(gst.getWidth()>0 && gst.getHeight()>0){
		string focusWindowStr = ofToString(1-focusWindowScaled.x/gst.getWidth()) + "," + ofToString(1-focusWindowScaled.y/gst.getHeight()) + ":" +
				ofToString(1-(focusWindowScaled.x + focusWindowScaled.width)/gst.getWidth()) + "," + ofToString(1-focusWindowScaled.y/gst.getHeight()) + ":" +
				ofToString(1-(focusWindowScaled.x + focusWindowScaled.width)/gst.getWidth()) + "," + ofToString(1-(focusWindowScaled.y+focusWindowScaled.height)/gst.getHeight()) + ":" +
				ofToString(1-focusWindowScaled.x/gst.getWidth()) + "," + ofToString(1-(focusWindowScaled.y+focusWindowScaled.height)/gst.getHeight());

		http.getUrl("http://"+cameraAddress+"/axis-cgi/param.cgi?action=update&ImageSource.I0.Focus.Window.W0="+focusWindowStr+"&timestamp="+ofToString(ofGetSystemTime()));
		requestFocusWindow();
		triggerAutoFocus();
	}
}

void ofxAxisGrabber::threadedFunction(){
	while(isThreadRunning()){
		u_long now = ofGetElapsedTimeMillis();
		updating = true;
		ofxHttpResponse response = http.getUrl("http://"+cameraAddress+"/axis-cgi/opticssetup.cgi?monitor=poll&timestamp="+ofToString(ofGetSystemTime()));
		if(response.status==200){
			cameraConnected = true;
			cameraAuth = true;
			Poco::XML::DOMParser parser;
			Poco::XML::Document * xml = parser.parseString(response.responseBody);
			focus = round(ofToFloat(xml->getElementsByTagName("opticsSetupState")->item(0)->attributes()->getNamedItem("focusPosition")->nodeValue())*297);
			prevFocus = focus;
			xml->getElementsByTagName("opticsSetupState")->item(0)->attributes()->getNamedItem("focusOperationInProgress")->nodeValue();
			focusMeasure = ofToInt(xml->getElementsByTagName("opticsSetupState")->item(0)->attributes()->getNamedItem("focusMeasure")->nodeValue());
			xml->getElementsByTagName("opticsSetupState")->item(0)->attributes()->getNamedItem("focusAssistantRunning")->nodeValue();
		}else{
			if(response.status==-1){
				cameraConnected = false;
			}else if(response.status==401){
				cameraAuth = false;
			}
			ofLogError("ofxAxisGrabber")<< "couldn't update parameters: " << response.status << ": " << response.reasonForStatus;
		}
		requestFocusWindow();
		checkExposure();
		checkIRFilterCut();
		checkCompression();
		updating = false;
		ofSleepMillis(paramRefreshRateMs);
	}
}

void ofxAxisGrabber::update(){
	gst.update();
	if(gst.isFrameNew()){
		framesInOneSec++;
		u_long now = ofGetElapsedTimeMicros();
		double oneSecTime = now-startTimeOneSecMicros;
		fps = double(framesInOneSec*1000000)/oneSecTime;
		if(oneSecTime>=1000000){
			startTimeOneSecMicros = now;
			framesInOneSec = 0;
		}
	}
	if(!getPocoThread().isRunning()) startThread();
}

bool ofxAxisGrabber::isFrameNew(){
	return gst.isFrameNew();
}

unsigned char * ofxAxisGrabber::getPixels(){
	return gst.getPixels();
}

ofPixels_<unsigned char> & ofxAxisGrabber::getPixelsRef(){
	return gst.getPixelsRef();
}

void ofxAxisGrabber::close(){
	if(started){
		gst.close();
		http.stop();
		stopThread();
		started = false;
	}
}

float ofxAxisGrabber::getHeight(){
	return gst.getHeight();
}

float ofxAxisGrabber::getWidth(){
	return gst.getWidth();
}

bool ofxAxisGrabber::setPixelFormat(ofPixelFormat pixelFormat){
	return false;
}

ofPixelFormat ofxAxisGrabber::getPixelFormat(){
	return OF_PIXELS_RGB;
}

void ofxAxisGrabber::setVerbose(bool bTalkToMe){

}

void ofxAxisGrabber::setDeviceID(int _deviceID){

}

void ofxAxisGrabber::setDesiredFrameRate(int framerate){
	desiredFramerate = framerate;
}

void ofxAxisGrabber::videoSettings(){

}

// axisgrabber only
void ofxAxisGrabber::triggerAutoFocus(){
	http.addUrl("http://"+cameraAddress+"/axis-cgi/opticssetup.cgi?autofocus=perform&timestamp="+ofToString(ofGetSystemTime()));
}

void ofxAxisGrabber::setAuth(string user, string pwd){
	http.setBasicAuthentication(user,pwd);
}

void ofxAxisGrabber::setParametersRefreshRate(int ms){
	paramRefreshRateMs = ms;
}

ofGstVideoUtils & ofxAxisGrabber::getGstUtils(){
	return gst;
}
<commit_msg>camera: add refresh ms to gui<commit_after>/*
 * ofxAxisGrabber.cpp
 *
 *  Created on: Sep 23, 2012
 *      Author: arturo
 */

#include "ofxAxisGrabber.h"
#include "Poco/DOM/DOMParser.h"
#include "Poco/DOM/Document.h"
#include "Poco/DOM/NodeList.h"
#include "Poco/DOM/NamedNodeMap.h"
#include "ofAppRunner.h"

ofxAxisGrabber::ofxAxisGrabber() {
	paramRefreshRateMs = 3000;
	desiredFramerate = 0;
	startTimeOneSecMicros = 0;
	framesInOneSec = 0;
	codec = H264;
	updating = false;
	started = false;

	parameters.add(focus.set("focus",100,0,297));
	parameters.add(manualIris.set("manualIris",true));
	parameters.add(exposure.set("exposure",50,0,100));
	parameters.add(irFilterCut.set("irFilterCut",0,0,2));
	parameters.add(compression.set("compression",30,0,100));
	parameters.add(paramRefreshRateMs.set("paramRefreshRateMs",3000,0,10000));
	parameters.add(fps.set("fps",0,0,60));
	parameters.add(cameraConnected.set("cameraConnected",false));
	parameters.add(cameraAuth.set("cameraAuth",false));
	prevFocus = focus;

	compression.addListener(this,&ofxAxisGrabber::compressionChanged);
	exposure.addListener(this,&ofxAxisGrabber::exposureChanged);
	irFilterCut.addListener(this,&ofxAxisGrabber::irFilterCutChanged);
	manualIris.addListener(this,&ofxAxisGrabber::setManualIris);
	focus.addListener(this,&ofxAxisGrabber::focusChanged);
}

//overwritten from ofBaseVideoGrabber
void ofxAxisGrabber::listDevices(){

}

void ofxAxisGrabber::setCodec(ofxAxisGrabber::AxisCodec _codec){
	codec = _codec;
}

void ofxAxisGrabber::setCameraAddress(string address){
	string parametersName = address;
	ofStringReplace(parametersName,".","_");
	parameters.setName(parametersName);
	cameraAddress = address;
}

string ofxAxisGrabber::getCameraAddress(){
	return cameraAddress;
}

void ofxAxisGrabber::setCompression(int _compression){
	compression = _compression;
}

bool ofxAxisGrabber::initGrabber(int w, int h){
	startTimeOneSecMicros = 0;
	framesInOneSec=0;
	fps=0;

	if(cameraAddress==""){
		ofLogError() << "cannot init axis grabber, must call setCameraAddress before initGrabber" << endl;
	}

	string codecStr = codec==MJPG?"mjpg":"h264";
	stringstream url;
	url << "rtsp://" << cameraAddress <<
			"/axis-media/media.amp?"
			"videocodec=" << codecStr <<
			"&resolution=" << w << "x" << h <<
			"&compression=" << compression <<
			"&mirror=0"
			"&rotation=180"
			"&textposition=top"
			"&textbackgroundcolor=black"
			"&textcolor=white"
			"&text=0"
			"&clock=0"
			"&date=0"
			"&overlayimage=0"
			"&fps=" << desiredFramerate <<
			"&audio=0"
			"&keyframe_interval=8"
			"&videobitrate=0"
			"&maxframesize=0";

	stringstream pipeline;
	pipeline << "rtspsrc location=\"" << url.str() << "\" latency=0 ! decodebin2 ! ffmpegcolorspace ! queue ";

	ofLogNotice("ofxAxisGrabber") << "pipeline: ";
	ofLogNotice("ofxAxisGrabber") << pipeline.str();
	bool ret = gst.setPipeline(pipeline.str(),24,true,w,h);

	//gst.loadMovie("http://10.42.0.23/axis-cgi/mjpg/video.cgi?fps=30&nbrofframes=0&resolution=640x480");
	//gst.loadMovie("rtsp://10.42.0.23:554/axis-media/media.amp?videocodec=h264");
	//player.loadMovie("rtsp://10.42.0.23:554/axis-media/media.amp?videocodec=h264&resolution="+ofToString(w)+"x"+ofToString(h)+"&compression=10&mirror=0&rotation=180&textposition=top&textbackgroundcolor=black&textcolor=white&text=0&clock=0&date=0&overlayimage=0&fps=0&audio=0&keyframe_interval=32&videobitrate=0&maxframesize=0");
	cameraConnected = ret;
	if(ret) {
		gst.play();

		http.setTimeoutSeconds(30);
		http.start();
		if(!getPocoThread().isRunning()) startThread();
	}else{
		ofLogError("ofxAxisGrabber") << "couldn't allocate gstreamer";
	}

	started = ret;
	return ret;
}

void ofxAxisGrabber::newResponse(ofxHttpResponse & response){
	if(response.status==-1){
		cameraConnected = false;
		http.clearQueue();
	}
}

void ofxAxisGrabber::focusChanged(int & focus){
	if(updating || cameraAddress=="") return;
	float step = float(focus - prevFocus)/297.;
	http.addUrl("http://"+cameraAddress+"/axis-cgi/opticssetup.cgi?rfocus="+ofToString(step)+"&timestamp="+ofToString(ofGetSystemTime()));
	prevFocus = focus;
}

string ofxAxisGrabber::getStrPropertyValue(string property){
	if(cameraAddress=="") return "";
	ofxHttpResponse response = http.getUrl("http://"+cameraAddress+"/axis-cgi/param.cgi?action=list&group="+property+"&timestamp="+ofToString(ofGetSystemTime()));
	if(response.status==200){
		return string(response.responseBody).substr(string(property).size()+1);
	}else{
		return "";
	}
}

int ofxAxisGrabber::getIntPropertyValue(string property){
	if(cameraAddress=="") return 0;
	string strValue = getStrPropertyValue(property);
	if(strValue!=""){
		return ofToInt(strValue);
	}else{
		return 0;
	}
}

float ofxAxisGrabber::getFloatPropertyValue(string property){
	if(cameraAddress=="") return 0;
	string strValue = getStrPropertyValue(property);
	if(strValue!=""){
		return ofToFloat(strValue);
	}else{
		return 0;
	}
}

template<typename T>
void ofxAxisGrabber::setPropertyValue(string property, T & value){
	if(cameraAddress=="") return;
	http.addUrl("http://"+cameraAddress+"/axis-cgi/param.cgi?action=update&"+property+"="+ofToString(value)+"&timestamp="+ofToString(ofGetSystemTime()));
}

void ofxAxisGrabber::exposureChanged(int & exposure){
	if(!updating)
		setPropertyValue("ImageSource.I0.Sensor.ExposureValue",exposure);
}

void ofxAxisGrabber::checkExposure(){
	if(cameraAddress=="") return;
	exposure = getIntPropertyValue("ImageSource.I0.Sensor.ExposureValue");
}

void ofxAxisGrabber::irFilterCutChanged(int & irFilterCut){
	if(!updating){
		switch(irFilterCut){
		case 0:
			setPropertyValue("ImageSource.I0.DayNight.IrCutFilter","auto");
			break;
		case 1:
			setPropertyValue("ImageSource.I0.DayNight.IrCutFilter","yes");
			break;
		case 2:
			setPropertyValue("ImageSource.I0.DayNight.IrCutFilter","no");
			break;
		}
	}
}

void ofxAxisGrabber::checkIRFilterCut(){
	string strIRFilter = getStrPropertyValue("ImageSource.I0.DayNight.IrCutFilter");
	if(strIRFilter=="auto"){
		irFilterCut=0;
	}else if(strIRFilter=="yes"){
		irFilterCut=1;
	}if(strIRFilter=="no"){
		irFilterCut=2;
	}
}

void ofxAxisGrabber::compressionChanged(int & compression){
	if(!updating)
		setPropertyValue("Image.I0.Appearance.Compression",compression);
}

void ofxAxisGrabber::checkCompression(){
	compression = getIntPropertyValue("Image.I0.Appearance.Compression");
}

void ofxAxisGrabber::requestFocusWindow(){
	ofxHttpResponse response = http.getUrl("http://"+cameraAddress+"/axis-cgi/param.cgi?action=list&group=ImageSource.I0.Focus.Window.W0&timestamp="+ofToString(ofGetSystemTime()));
	if(response.status==200){
		string focusWindowStr = response.responseBody;
		focusWindowStr = focusWindowStr.substr(string("ImageSource.I0.Focus.Window.W0=").size());
		vector<string> coords = ofSplitString(focusWindowStr,":");

		focusWindow.x = ofToFloat(ofSplitString(coords[0],",")[0]);
		focusWindow.y = ofToFloat(ofSplitString(coords[0],",")[1]);
		focusWindow.width = -(ofToFloat(ofSplitString(coords[1],",")[0])-focusWindow.x);
		focusWindow.height = -(ofToFloat(ofSplitString(coords[2],",")[1])-focusWindow.y);
		focusWindow.y = 1-focusWindow.y;
		focusWindow.x = 1-focusWindow.x;

		focusWindowScaled = focusWindow;
		focusWindowScaled.x*=gst.getWidth();
		focusWindowScaled.y*=gst.getHeight();
		focusWindowScaled.width*=gst.getWidth();
		focusWindowScaled.height*=gst.getHeight();
	}
}

void ofxAxisGrabber::setManualIris(bool & manual){
	http.addUrl("http://"+cameraAddress+"//axis-cgi/irissetup.cgi?automatic=" + string(manual?"no":"yes") + "&timestamp="+ofToString(ofGetSystemTime()));
}

ofRectangle & ofxAxisGrabber::getFocusWindow(){
	return focusWindowScaled;
}

void ofxAxisGrabber::setFocusWindow(const ofRectangle & focusWindow){
	focusWindowScaled = focusWindow;
	setFocusWindow();
}

void ofxAxisGrabber::setFocusWindow(){
	if(gst.getWidth()>0 && gst.getHeight()>0){
		string focusWindowStr = ofToString(1-focusWindowScaled.x/gst.getWidth()) + "," + ofToString(1-focusWindowScaled.y/gst.getHeight()) + ":" +
				ofToString(1-(focusWindowScaled.x + focusWindowScaled.width)/gst.getWidth()) + "," + ofToString(1-focusWindowScaled.y/gst.getHeight()) + ":" +
				ofToString(1-(focusWindowScaled.x + focusWindowScaled.width)/gst.getWidth()) + "," + ofToString(1-(focusWindowScaled.y+focusWindowScaled.height)/gst.getHeight()) + ":" +
				ofToString(1-focusWindowScaled.x/gst.getWidth()) + "," + ofToString(1-(focusWindowScaled.y+focusWindowScaled.height)/gst.getHeight());

		http.getUrl("http://"+cameraAddress+"/axis-cgi/param.cgi?action=update&ImageSource.I0.Focus.Window.W0="+focusWindowStr+"&timestamp="+ofToString(ofGetSystemTime()));
		requestFocusWindow();
		triggerAutoFocus();
	}
}

void ofxAxisGrabber::threadedFunction(){
	while(isThreadRunning()){
		u_long now = ofGetElapsedTimeMillis();
		updating = true;
		ofxHttpResponse response = http.getUrl("http://"+cameraAddress+"/axis-cgi/opticssetup.cgi?monitor=poll&timestamp="+ofToString(ofGetSystemTime()));
		if(response.status==200){
			cameraConnected = true;
			cameraAuth = true;
			Poco::XML::DOMParser parser;
			Poco::XML::Document * xml = parser.parseString(response.responseBody);
			focus = round(ofToFloat(xml->getElementsByTagName("opticsSetupState")->item(0)->attributes()->getNamedItem("focusPosition")->nodeValue())*297);
			prevFocus = focus;
			xml->getElementsByTagName("opticsSetupState")->item(0)->attributes()->getNamedItem("focusOperationInProgress")->nodeValue();
			focusMeasure = ofToInt(xml->getElementsByTagName("opticsSetupState")->item(0)->attributes()->getNamedItem("focusMeasure")->nodeValue());
			xml->getElementsByTagName("opticsSetupState")->item(0)->attributes()->getNamedItem("focusAssistantRunning")->nodeValue();
		}else{
			if(response.status==-1){
				cameraConnected = false;
			}else if(response.status==401){
				cameraAuth = false;
			}
			ofLogError("ofxAxisGrabber")<< "couldn't update parameters: " << response.status << ": " << response.reasonForStatus;
		}
		requestFocusWindow();
		checkExposure();
		checkIRFilterCut();
		checkCompression();
		updating = false;
		ofSleepMillis(paramRefreshRateMs);
	}
}

void ofxAxisGrabber::update(){
	gst.update();
	if(gst.isFrameNew()){
		framesInOneSec++;
		u_long now = ofGetElapsedTimeMicros();
		double oneSecTime = now-startTimeOneSecMicros;
		fps = double(framesInOneSec*1000000)/oneSecTime;
		if(oneSecTime>=1000000){
			startTimeOneSecMicros = now;
			framesInOneSec = 0;
		}
	}
	if(!getPocoThread().isRunning()) startThread();
}

bool ofxAxisGrabber::isFrameNew(){
	return gst.isFrameNew();
}

unsigned char * ofxAxisGrabber::getPixels(){
	return gst.getPixels();
}

ofPixels_<unsigned char> & ofxAxisGrabber::getPixelsRef(){
	return gst.getPixelsRef();
}

void ofxAxisGrabber::close(){
	if(started){
		gst.close();
		http.stop();
		stopThread();
		started = false;
	}
}

float ofxAxisGrabber::getHeight(){
	return gst.getHeight();
}

float ofxAxisGrabber::getWidth(){
	return gst.getWidth();
}

bool ofxAxisGrabber::setPixelFormat(ofPixelFormat pixelFormat){
	return false;
}

ofPixelFormat ofxAxisGrabber::getPixelFormat(){
	return OF_PIXELS_RGB;
}

void ofxAxisGrabber::setVerbose(bool bTalkToMe){

}

void ofxAxisGrabber::setDeviceID(int _deviceID){

}

void ofxAxisGrabber::setDesiredFrameRate(int framerate){
	desiredFramerate = framerate;
}

void ofxAxisGrabber::videoSettings(){

}

// axisgrabber only
void ofxAxisGrabber::triggerAutoFocus(){
	http.addUrl("http://"+cameraAddress+"/axis-cgi/opticssetup.cgi?autofocus=perform&timestamp="+ofToString(ofGetSystemTime()));
}

void ofxAxisGrabber::setAuth(string user, string pwd){
	http.setBasicAuthentication(user,pwd);
}

void ofxAxisGrabber::setParametersRefreshRate(int ms){
	paramRefreshRateMs = ms;
}

ofGstVideoUtils & ofxAxisGrabber::getGstUtils(){
	return gst;
}
<|endoftext|>


<commit_before>#pragma once
#ifndef NIFTY_GRAPH_RAG_DETAIL_RAG_COMPUTE_GRID_RAG_HXX
#define NIFTY_GRAPH_RAG_DETAIL_RAG_COMPUTE_GRID_RAG_HXX

#include <random>
#include <functional>
#include <ctime>
#include <stack>
#include <algorithm>
#include <unordered_set>

// for strange reason travis does not find the boost flat set
#ifdef WITHIN_TRAVIS
#include <set>
#define __setimpl std::set
#else
#include <boost/container/flat_set.hpp>
#define __setimpl boost::container::flat_set
#endif

#include "nifty/graph/rag/grid_rag_labels.hxx"
#include "nifty/marray/marray.hxx"
#include "nifty/graph/simple_graph.hxx"
#include "nifty/parallel/threadpool.hxx"
#include "nifty/tools/timer.hxx"
#include "nifty/tools/for_each_coordinate.hxx"
//#include "nifty/graph/detail/contiguous_indices.hxx"

namespace nifty{
namespace graph{

template<size_t DIM, class LABEL_TYPE>
class ExplicitLabels;

template<size_t DIM, class LABELS_PROXY>
class GridRag;

namespace detail_rag{

template< class GRID_RAG>
struct ComputeRag;

template<size_t DIM, class LABEL_TYPE>
struct ComputeRag< GridRag<DIM,  ExplicitLabels<DIM, LABEL_TYPE> > > {

    template<class S>
    static void computeRag(
        GridRag<DIM,  ExplicitLabels<DIM, LABEL_TYPE> > & rag,
        const S & settings
    ){
        typedef GridRag<DIM,  ExplicitLabels<DIM, LABEL_TYPE> >  Graph;
        typedef std::array<int64_t, DIM> Coord;
        typedef typename Graph::NodeAdjacency NodeAdjacency;
        typedef typename Graph::EdgeStorage EdgeStorage;

        const auto labelsProxy = rag.labelsProxy();
        const auto numberOfLabels = labelsProxy.numberOfLabels();
        const auto labels = labelsProxy.labels();
        const auto & shape = labelsProxy.shape();

        nifty::parallel::ParallelOptions pOpts(settings.numberOfThreads);

        // assign the number of nodes to the graph
        rag.assign(numberOfLabels);

        auto makeCoord2 = [](const Coord & coord,const size_t axis){
            Coord coord2 = coord;
            coord2[axis] += 1;
            return coord2;
        };

        if(pOpts.getActualNumThreads()<=1){
            nifty::tools::forEachCoordinate(shape,[&](const Coord & coord){
                const auto lU = labels(coord);
                for(size_t axis=0; axis<DIM; ++axis){
                    auto coord2 = makeCoord2(coord, axis);
                    if(coord2[axis] < shape[axis]){
                        const auto lV = labels(coord2);
                        if(lU != lV){
                            rag.insertEdge(lU,lV);
                        }
                    }
                }
            });
        }
        else{
            nifty::parallel::ThreadPool threadpool(pOpts);
            struct PerThread{
                std::vector< __setimpl<uint64_t> > adjacency;
            };

            std::vector<PerThread> perThreadDataVec(pOpts.getActualNumThreads());
            for(size_t i=0; i<perThreadDataVec.size(); ++i)
                perThreadDataVec[i].adjacency.resize(numberOfLabels);

            // collect the node-adjacency sets in parallel which needs to be merged later
            nifty::tools::parallelForEachCoordinate(threadpool, shape,[&](const int tid, const Coord & coord){
                auto & adjacency = perThreadDataVec[tid].adjacency;
                const auto lU = labels(coord);
                for(size_t axis=0; axis<DIM; ++axis){
                    auto coord2 = makeCoord2(coord, axis);
                    if(coord2[axis] < shape[axis]){
                        const auto lV = labels(coord2);
                        if(lU != lV){
                            adjacency[lV].insert(lU);
                            adjacency[lU].insert(lV);
                        }
                    }
                }
            });
            // merge the node adjacency sets for each node
            nifty::parallel::parallel_foreach(threadpool, numberOfLabels, [&](int tid, int label){
                auto & set0 = perThreadDataVec[0].adjacency[label];
                for(size_t i=1; i<perThreadDataVec.size(); ++i){
                    const auto & setI = perThreadDataVec[i].adjacency[label];
                    set0.insert(setI.begin(), setI.end());
                }
                for(auto otherNode : set0)
                     rag.nodes_[label].insert(NodeAdjacency(otherNode));
            });

            // insert the edge index for each edge
            uint64_t edgeIndex = 0;
            auto & edges = rag.edges_;
            for(uint64_t u = 0; u< numberOfLabels; ++u){
                for(auto & vAdj :  rag.nodes_[u]){
                    const auto v = vAdj.node();
                    if(u < v){
                        edges.push_back(EdgeStorage(u, v));
                        vAdj.changeEdgeIndex(edgeIndex);
                        auto fres =  rag.nodes_[v].find(NodeAdjacency(u));
                        fres->changeEdgeIndex(edgeIndex);
                        ++edgeIndex;
                    }
                }
            }
        }
    }
};

} // end namespace detail_rag

} // end namespace graph
} // end namespace nifty

#endif /* NIFTY_GRAPH_RAG_DETAIL_RAG_COMPUTE_GRID_RAG_HXX */
<commit_msg>cleaned up rag impl (untested)<commit_after>#pragma once
#ifndef NIFTY_GRAPH_RAG_DETAIL_RAG_COMPUTE_GRID_RAG_HXX
#define NIFTY_GRAPH_RAG_DETAIL_RAG_COMPUTE_GRID_RAG_HXX

#include <random>
#include <functional>
#include <ctime>
#include <stack>
#include <algorithm>
#include <unordered_set>

// for strange reason travis does not find the boost flat set
#ifdef WITHIN_TRAVIS
#include <set>
#define __setimpl std::set
#else
#include <boost/container/flat_set.hpp>
#define __setimpl boost::container::flat_set
#endif

#include "nifty/graph/rag/grid_rag_labels.hxx"
#include "nifty/marray/marray.hxx"
#include "nifty/graph/simple_graph.hxx"
#include "nifty/parallel/threadpool.hxx"
#include "nifty/tools/timer.hxx"
#include "nifty/tools/for_each_coordinate.hxx"
//#include "nifty/graph/detail/contiguous_indices.hxx"

namespace nifty{
namespace graph{

template<size_t DIM, class LABEL_TYPE>
class ExplicitLabels;

template<size_t DIM, class LABELS_PROXY>
class GridRag;

namespace detail_rag{

template< class GRID_RAG>
struct ComputeRag;

template<size_t DIM, class LABEL_TYPE>
struct ComputeRag< GridRag<DIM,  ExplicitLabels<DIM, LABEL_TYPE> > > {

    template<class S>
    static void computeRag(
        GridRag<DIM,  ExplicitLabels<DIM, LABEL_TYPE> > & rag,
        const S & settings
    ){
        typedef GridRag<DIM,  ExplicitLabels<DIM, LABEL_TYPE> >  Graph;
        typedef std::array<int64_t, DIM> Coord;
        typedef typename Graph::NodeAdjacency NodeAdjacency;
        typedef typename Graph::EdgeStorage EdgeStorage;

        const auto labelsProxy = rag.labelsProxy();
        const auto numberOfLabels = labelsProxy.numberOfLabels();
        const auto labels = labelsProxy.labels();
        const auto & shape = labelsProxy.shape();

        nifty::parallel::ParallelOptions pOpts(settings.numberOfThreads);

        // assign the number of nodes to the graph
        rag.assign(numberOfLabels);

        auto makeCoord2 = [](const Coord & coord,const size_t axis){
            Coord coord2 = coord;
            coord2[axis] += 1;
            return coord2;
        };

        if(pOpts.getActualNumThreads()<=1){
            nifty::tools::forEachCoordinate(shape,[&](const Coord & coord){
                const auto lU = labels(coord);
                for(size_t axis=0; axis<DIM; ++axis){
                    auto coord2 = makeCoord2(coord, axis);
                    if(coord2[axis] < shape[axis]){
                        const auto lV = labels(coord2);
                        if(lU != lV){
                            rag.insertEdge(lU,lV);
                        }
                    }
                }
            });
        }
        else{
            nifty::parallel::ThreadPool threadpool(pOpts);
            struct PerThread{
                std::vector< __setimpl<uint64_t> > adjacency;
            };

            std::vector<PerThread> perThreadDataVec(pOpts.getActualNumThreads());
            for(size_t i=0; i<perThreadDataVec.size(); ++i)
                perThreadDataVec[i].adjacency.resize(numberOfLabels);

            // collect the node-adjacency sets in parallel which needs to be merged later
            nifty::tools::parallelForEachCoordinate(threadpool, shape,[&](const int tid, const Coord & coord){
                auto & adjacency = perThreadDataVec[tid].adjacency;
                const auto lU = labels(coord);
                for(size_t axis=0; axis<DIM; ++axis){
                    auto coord2 = makeCoord2(coord, axis);
                    if(coord2[axis] < shape[axis]){
                        const auto lV = labels(coord2);
                        if(lU != lV){
                            adjacency[lV].insert(lU);
                            adjacency[lU].insert(lV);
                        }
                    }
                }
            });

            // merge the node adjacency sets for each node
            nifty::parallel::parallel_foreach(threadpool, numberOfLabels, [&](int tid, int label){
                auto & set0 = perThreadDataVec[0].adjacency[label];
                for(size_t i=1; i<perThreadDataVec.size(); ++i){
                    const auto & setI = perThreadDataVec[i].adjacency[label];
                    set0.insert(setI.begin(), setI.end());
                }
                for(auto otherNode : set0)
                     rag.nodes_[label].insert(NodeAdjacency(otherNode));
            });

            // insert the edge index for each edge
            uint64_t edgeIndex = 0;
            auto & edges = rag.edges_;
            for(uint64_t u = 0; u< numberOfLabels; ++u){
                for(auto & vAdj :  rag.nodes_[u]){
                    const auto v = vAdj.node();
                    if(u < v){
                        edges.push_back(EdgeStorage(u, v));
                        vAdj.changeEdgeIndex(edgeIndex);
                        auto fres =  rag.nodes_[v].find(NodeAdjacency(u));
                        fres->changeEdgeIndex(edgeIndex);
                        ++edgeIndex;
                    }
                }
            }
        }
    }
};

} // end namespace detail_rag

} // end namespace graph
} // end namespace nifty

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


<commit_before>#include "Halide.h"

using namespace Halide;

class BufferCopy : public Halide::Generator<BufferCopy> {
public:
    Input<Func> input {"input", Float(32), 2 };

    Output<Func> output {"output", Float(32), 2 };

    Func dev_1, host_1, dev_2;
    Var x, y;

    Expr check_eq(Expr a, Expr b, const char *name) {
        return require(a == b, a, "!=", b, "@", name, "(", x, ",", y, ")");
    }

    void generate() {
        // We're going to have a four stage pipeline where we do work
        // on-device, on the host, on the device again, and finally on
        // the host again. In between each stage we'll schedule an
        // explicit copy in one direction or the other.

        dev_1(x, y) = input(x, y) + 1;
        host_1(x, y) = dev_1(x, y) + 1;
        dev_2(x, y) = host_1(x, y) + 1;
        output(x, y) = dev_2(x, y) + 1;
    }

    void schedule() {
        if (get_target().has_gpu_feature()) {
            Var tx, ty, xi, yi;

            // Set up a complicated nested tiling so that the two of the
            // buffer_copy stages are pulling a subset and two are pulling an entire buffer.
            output.compute_root()
                .tile(x, y, tx, ty, x, y, 64, 64);

            // dev_1 does computed over 64x64 kernel launches
            dev_1.compute_at(output, tx)
                .gpu_tile(x, y, xi, yi, 8, 8);

            // dev_2 does 32x32 kernel launches
            dev_2.compute_at(output, tx)
                .tile(x, y, tx, ty, x, y, 32, 32)
                .gpu_tile(x, y, xi, yi, 8, 8);

            // host_1 is computed per 32x32 tile of dev_2
            host_1.compute_at(dev_2, tx);

            // TODO: Calling in() on Input<Func> doesn't really work.
            Func(input).in().compute_root();

            // pulls a 64x64 subset of the input into a region of a GPU buffer to be consumed by dev_1
            Func(input).in().in(dev_1).copy_to_device().compute_at(output, tx).store_root();

            // pulls a 32x32 subset from dev to host to be consumed by host_1
            dev_1.in(host_1).copy_to_host().compute_at(dev_2, tx);

            // pulls an entire 32x32 buffer back to the device to be consumed by dev_2
            host_1.in(dev_2).copy_to_device().compute_at(dev_2, tx);

            // pulls an entire 64x64 buffer back to the host to be consumed by the output
            dev_2.in(output).copy_to_host().compute_at(output, tx);
        }
    }
};

HALIDE_REGISTER_GENERATOR(BufferCopy, "buffer_copy");
<commit_msg>Fix generator registration<commit_after>#include "Halide.h"

using namespace Halide;

class BufferCopy : public Halide::Generator<BufferCopy> {
public:
    Input<Func> input {"input", Float(32), 2 };

    Output<Func> output {"output", Float(32), 2 };

    Func dev_1, host_1, dev_2;
    Var x, y;

    Expr check_eq(Expr a, Expr b, const char *name) {
        return require(a == b, a, "!=", b, "@", name, "(", x, ",", y, ")");
    }

    void generate() {
        // We're going to have a four stage pipeline where we do work
        // on-device, on the host, on the device again, and finally on
        // the host again. In between each stage we'll schedule an
        // explicit copy in one direction or the other.

        dev_1(x, y) = input(x, y) + 1;
        host_1(x, y) = dev_1(x, y) + 1;
        dev_2(x, y) = host_1(x, y) + 1;
        output(x, y) = dev_2(x, y) + 1;
    }

    void schedule() {
        if (get_target().has_gpu_feature()) {
            Var tx, ty, xi, yi;

            // Set up a complicated nested tiling so that the two of the
            // buffer_copy stages are pulling a subset and two are pulling an entire buffer.
            output.compute_root()
                .tile(x, y, tx, ty, x, y, 64, 64);

            // dev_1 does computed over 64x64 kernel launches
            dev_1.compute_at(output, tx)
                .gpu_tile(x, y, xi, yi, 8, 8);

            // dev_2 does 32x32 kernel launches
            dev_2.compute_at(output, tx)
                .tile(x, y, tx, ty, x, y, 32, 32)
                .gpu_tile(x, y, xi, yi, 8, 8);

            // host_1 is computed per 32x32 tile of dev_2
            host_1.compute_at(dev_2, tx);

            // TODO: Calling in() on Input<Func> doesn't really work.
            Func(input).in().compute_root();

            // pulls a 64x64 subset of the input into a region of a GPU buffer to be consumed by dev_1
            Func(input).in().in(dev_1).copy_to_device().compute_at(output, tx).store_root();

            // pulls a 32x32 subset from dev to host to be consumed by host_1
            dev_1.in(host_1).copy_to_host().compute_at(dev_2, tx);

            // pulls an entire 32x32 buffer back to the device to be consumed by dev_2
            host_1.in(dev_2).copy_to_device().compute_at(dev_2, tx);

            // pulls an entire 64x64 buffer back to the host to be consumed by the output
            dev_2.in(output).copy_to_host().compute_at(output, tx);
        }
    }
};

HALIDE_REGISTER_GENERATOR(BufferCopy, buffer_copy);
<|endoftext|>