<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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.
 *
 ***************************************************************/

#ifdef _NO_CONDOR_
#include <sys/types.h> // for fstat, struct stat
#include <sys/stat.h> // for fstat, struct stat
#include <unistd.h> // for fstat, struct stat
#include <limits.h> // for _POSIX_PATH_MAX
#include <string.h> // for strcpy
#include <stdlib.h> // for atol
#include <assert.h> // for assert
#include <errno.h> // for errno
#else
#include "condor_common.h"
#endif

#include "ClassAdLogEntry.h"
#include "ClassAdLogProber.h"
#include "ClassAdLogParser.h"

//! constructor
ClassAdLogProber::ClassAdLogProber()
{
	last_mod_time = 0;
	last_size = 0;
	last_seq_num = 0;
	last_creation_time = 0;

	cur_probed_mod_time = 0;
	cur_probed_size = 0;
	cur_probed_seq_num = 0;
	cur_probed_creation_time = 0;
}

//! destructor
ClassAdLogProber::~ClassAdLogProber()
{}

//**************************************************************************
// Accessors
//**************************************************************************
void
ClassAdLogProber::setJobQueueName(const char* jqn)
{
	assert(jqn);
	strcpy(job_queue_name, jqn);
}

char*
ClassAdLogProber::getJobQueueName()
{
	return job_queue_name;
}

void
ClassAdLogProber::setLastModifiedTime(time_t t)
{
	last_mod_time = t;
}

time_t
ClassAdLogProber::getLastModifiedTime()
{
	return last_mod_time;
}

void
ClassAdLogProber::setLastSize(size_t s)
{
	last_size = s;
}

size_t
ClassAdLogProber::getLastSize()
{
	return last_size;
}

long int
ClassAdLogProber::getLastSequenceNumber()
{
	return last_seq_num;
}

void
ClassAdLogProber::setLastSequenceNumber(long int seq_num)
{
	last_seq_num = seq_num;
}

time_t
ClassAdLogProber::getLastCreationTime()
{
	return last_creation_time;
}

void
ClassAdLogProber::setLastCreationTime(time_t ctime)
{
	last_creation_time = ctime;
}

long int
ClassAdLogProber::getCurProbedSequenceNumber() {
	return cur_probed_seq_num;
}

long int
ClassAdLogProber::getCurProbedCreationTime() {
	return cur_probed_creation_time;
}

//! probe job_queue.log file
ProbeResultType
ClassAdLogProber::probe(ClassAdLogEntry *curCALogEntry,
			  int job_queue_fd)
{
	FileOpErrCode   st;
	int op_type;
	struct stat filestat;

	//TODO: should use condor's StatInfo instead.
	if (fstat(job_queue_fd, &filestat) == -1)
		dprintf(D_ALWAYS,"ERROR: calling stat()\n");

	dprintf(D_FULLDEBUG, "=== Current Probing Information ===\n");
	dprintf(D_FULLDEBUG, "fsize: %ld\t\tmtime: %ld\n",
				(long)filestat.st_size, (long)filestat.st_mtime);

	// get the new state
	cur_probed_mod_time = filestat.st_mtime;
	cur_probed_size = filestat.st_size;

	ClassAdLogParser caLogParser;

	caLogParser.setFileDescriptor(job_queue_fd);
	caLogParser.setNextOffset(0);
	st = caLogParser.readLogEntry(op_type);

	if (FILE_FATAL_ERROR == st) {
		return PROBE_FATAL_ERROR;
	}
	if (st != FILE_READ_SUCCESS) {
		return PROBE_ERROR;
	}

	if ( caLogParser.getCurCALogEntry()->op_type !=
		 CondorLogOp_LogHistoricalSequenceNumber )
	{
		dprintf(D_ALWAYS,
				"ERROR: quill prober expects first classad log entry to be "
				"type %d, but sees %d instead.",
				CondorLogOp_LogHistoricalSequenceNumber,
				caLogParser.getCurCALogEntry()->op_type);
		return PROBE_FATAL_ERROR;
	}

	dprintf(D_FULLDEBUG, "first log entry: %s %s %s\n",
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key,
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->name,
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);
	cur_probed_seq_num =
		atol(((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key);
	cur_probed_creation_time =
		atol(((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);

	if (last_size == 0) {
			// starting phase
		return INIT_QUILL;
	}

	if(cur_probed_seq_num != last_seq_num) {
		return COMPRESSED;
	}

	caLogParser.setNextOffset(curCALogEntry->offset);
	st = caLogParser.readLogEntry(op_type);

	if (FILE_FATAL_ERROR == st) {
		return PROBE_FATAL_ERROR;
	}
	if (st != FILE_READ_EOF && st != FILE_READ_SUCCESS) {
		return PROBE_ERROR;
	}

	if((filestat.st_size == last_size) &&
	   caLogParser.getCurCALogEntry()->equal(curCALogEntry)) {
			// File size and contents stay the same
		return NO_CHANGE;
	}
	else if((filestat.st_size > last_size) &&
			caLogParser.getCurCALogEntry()->equal(curCALogEntry)) {
			// File has been increased and new entries have been added
		return ADDITION;
	}
		//if it wasn't captured by any of the above cases,
		//it must have been an error
	return PROBE_ERROR;
}

void
ClassAdLogProber::incrementProbeInfo() {
	// store the currently probed stat
	last_mod_time = cur_probed_mod_time;
	last_size = cur_probed_size;

	last_seq_num = cur_probed_seq_num;
	last_creation_time = cur_probed_creation_time;
}
<commit_msg>Added syslog alternative to ClassAdLogProber.cpp when _NO_CONDOR_ (#1247)<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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.
 *
 ***************************************************************/

#ifdef _NO_CONDOR_
#include <sys/types.h> // for fstat, struct stat
#include <sys/stat.h> // for fstat, struct stat
#include <unistd.h> // for fstat, struct stat
#include <limits.h> // for _POSIX_PATH_MAX
#include <string.h> // for strcpy
#include <stdlib.h> // for atol
#include <assert.h> // for assert
#include <errno.h> // for errno
#include <syslog.h> // for syslog, LOG_ERR, LOG_DEBUG
#else
#include "condor_common.h"
#endif

#include "ClassAdLogEntry.h"
#include "ClassAdLogProber.h"
#include "ClassAdLogParser.h"

//! constructor
ClassAdLogProber::ClassAdLogProber()
{
	last_mod_time = 0;
	last_size = 0;
	last_seq_num = 0;
	last_creation_time = 0;

	cur_probed_mod_time = 0;
	cur_probed_size = 0;
	cur_probed_seq_num = 0;
	cur_probed_creation_time = 0;
}

//! destructor
ClassAdLogProber::~ClassAdLogProber()
{}

//**************************************************************************
// Accessors
//**************************************************************************
void
ClassAdLogProber::setJobQueueName(const char* jqn)
{
	assert(jqn);
	strcpy(job_queue_name, jqn);
}

char*
ClassAdLogProber::getJobQueueName()
{
	return job_queue_name;
}

void
ClassAdLogProber::setLastModifiedTime(time_t t)
{
	last_mod_time = t;
}

time_t
ClassAdLogProber::getLastModifiedTime()
{
	return last_mod_time;
}

void
ClassAdLogProber::setLastSize(size_t s)
{
	last_size = s;
}

size_t
ClassAdLogProber::getLastSize()
{
	return last_size;
}

long int
ClassAdLogProber::getLastSequenceNumber()
{
	return last_seq_num;
}

void
ClassAdLogProber::setLastSequenceNumber(long int seq_num)
{
	last_seq_num = seq_num;
}

time_t
ClassAdLogProber::getLastCreationTime()
{
	return last_creation_time;
}

void
ClassAdLogProber::setLastCreationTime(time_t ctime)
{
	last_creation_time = ctime;
}

long int
ClassAdLogProber::getCurProbedSequenceNumber() {
	return cur_probed_seq_num;
}

long int
ClassAdLogProber::getCurProbedCreationTime() {
	return cur_probed_creation_time;
}

//! probe job_queue.log file
ProbeResultType
ClassAdLogProber::probe(ClassAdLogEntry *curCALogEntry,
			  int job_queue_fd)
{
	FileOpErrCode   st;
	int op_type;
	struct stat filestat;

	//TODO: should use condor's StatInfo instead.
	if (fstat(job_queue_fd, &filestat) == -1)
#ifdef _NO_CONDOR_
		syslog(LOG_ERR, "ERROR: calling stat(): errno=%d (%m)", errno);

	syslog(LOG_DEBUG, "=== Current Probing Information ===");
	syslog(LOG_DEBUG,
		   "fsize: %ld\t\tmtime: %ld",
		   (long)filestat.st_size, (long)filestat.st_mtime);
#else
		dprintf(D_ALWAYS,"ERROR: calling stat()\n");

	dprintf(D_FULLDEBUG, "=== Current Probing Information ===\n");
	dprintf(D_FULLDEBUG, "fsize: %ld\t\tmtime: %ld\n",
				(long)filestat.st_size, (long)filestat.st_mtime);
#endif

	// get the new state
	cur_probed_mod_time = filestat.st_mtime;
	cur_probed_size = filestat.st_size;

	ClassAdLogParser caLogParser;

	caLogParser.setFileDescriptor(job_queue_fd);
	caLogParser.setNextOffset(0);
	st = caLogParser.readLogEntry(op_type);

	if (FILE_FATAL_ERROR == st) {
		return PROBE_FATAL_ERROR;
	}
	if (st != FILE_READ_SUCCESS) {
		return PROBE_ERROR;
	}

	if ( caLogParser.getCurCALogEntry()->op_type !=
		 CondorLogOp_LogHistoricalSequenceNumber )
	{
#ifdef _NO_CONDOR_
		syslog(LOG_ERR,
			   "ERROR: prober expects first classad log entry to be "
			   "type %d, but sees %d instead.",
			   CondorLogOp_LogHistoricalSequenceNumber,
			   caLogParser.getCurCALogEntry()->op_type);
#else
		dprintf(D_ALWAYS,
				"ERROR: quill prober expects first classad log entry to be "
				"type %d, but sees %d instead.",
				CondorLogOp_LogHistoricalSequenceNumber,
				caLogParser.getCurCALogEntry()->op_type);
#endif
		return PROBE_FATAL_ERROR;
	}

#ifdef _NO_CONDOR_
	syslog(LOG_DEBUG,
		   "first log entry: %s %s %s",
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key,
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->name,
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);
#else
	dprintf(D_FULLDEBUG, "first log entry: %s %s %s\n",
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key,
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->name,
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);
#endif
	cur_probed_seq_num =
		atol(((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key);
	cur_probed_creation_time =
		atol(((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);

	if (last_size == 0) {
			// starting phase
		return INIT_QUILL;
	}

	if(cur_probed_seq_num != last_seq_num) {
		return COMPRESSED;
	}

	caLogParser.setNextOffset(curCALogEntry->offset);
	st = caLogParser.readLogEntry(op_type);

	if (FILE_FATAL_ERROR == st) {
		return PROBE_FATAL_ERROR;
	}
	if (st != FILE_READ_EOF && st != FILE_READ_SUCCESS) {
		return PROBE_ERROR;
	}

	if((filestat.st_size == last_size) &&
	   caLogParser.getCurCALogEntry()->equal(curCALogEntry)) {
			// File size and contents stay the same
		return NO_CHANGE;
	}
	else if((filestat.st_size > last_size) &&
			caLogParser.getCurCALogEntry()->equal(curCALogEntry)) {
			// File has been increased and new entries have been added
		return ADDITION;
	}
		//if it wasn't captured by any of the above cases,
		//it must have been an error
	return PROBE_ERROR;
}

void
ClassAdLogProber::incrementProbeInfo() {
	// store the currently probed stat
	last_mod_time = cur_probed_mod_time;
	last_size = cur_probed_size;

	last_seq_num = cur_probed_seq_num;
	last_creation_time = cur_probed_creation_time;
}
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2016 Intel Corporation                                         //
//                                                                          //
// 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 <chrono>

#include "OSPRayFixture.h"

#include "commandline/Utility.h"
#include "pico_bench/pico_bench.h"

using std::cout;
using std::endl;
using std::string;

// NOTE(jda) - Implement make_unique() as it didn't show up until C++14...
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique(Args&& ...args)
{
  return std::unique_ptr<T>(new T( std::forward<Args>(args)... ));
}

void printUsageAndExit()
{
  cout << "Usage: ospBenchmark [options] model_file" << endl;

  cout << endl << "Args:" << endl;

  cout << endl;
  cout << "    model_file --> Scene used for benchmarking, supported types"
            << " are:" << endl;
  cout << "                   stl, msg, tri, xml, obj, hbp, x3d" << endl;

  cout << endl;
  cout << "Options:" << endl;

  cout << endl;
  cout << "**generic rendering options**" << endl;

  cout << endl;
  cout << "    -i | --image --> Specify the base filename to write the"
       << " framebuffer to a file." << endl;
  cout << "                     If ommitted, no file will be written." << endl;
  cout << "                     NOTE: this option adds '.ppm' to the end of the"
       << " filename" << endl;

  cout << endl;
  cout << "    -w | --width --> Specify the width of the benchmark frame"
       << endl;
  cout << "                     default: 1024" << endl;

  cout << endl;
  cout << "    -h | --height --> Specify the height of the benchmark frame"
       << endl;
  cout << "                      default: 1024" << endl;

  cout << endl;
  cout << "    -r | --renderer --> Specify the renderer to be benchmarked."
       << endl;
  cout << "                        Ex: -r pathtracer" << endl;
  cout << "                        default: ao1" << endl;

  cout << endl;
  cout << "    -bg | --background --> Specify the background color: R G B"
       << endl;

  cout << endl;
  cout << "    -wf | --warmup --> Specify the number of warmup frames: N"
       << endl;
  cout << "                       default: 10" << endl;

  cout << endl;
  cout << "    -bf | --bench --> Specify the number of benchmark frames: N"
       << endl;
  cout << "                      default: 100" << endl;

  cout << endl;
  cout << "    -lft | --log-frame-times --> Log frame time in ms for every frame rendered"
       << endl;

  cout << endl;
  cout << "**camera rendering options**" << endl;

  cout << endl;
  cout << "    -vp | --eye --> Specify the camera eye as: ex ey ez " << endl;

  cout << endl;
  cout << "    -vi | --gaze --> Specify the camera gaze point as: ix iy iz "
       << endl;

  cout << endl;
  cout << "    -vu | --up --> Specify the camera up as: ux uy uz " << endl;

  cout << endl;
  cout << "**volume rendering options**" << endl;

  cout << endl;
  cout << "    -s | --sampling-rate --> Specify the sampling rate for volumes."
       << endl;
  cout << "                             default: 0.125" << endl;

  cout << endl;
  cout << "    -dr | --data-range --> Specify the data range for volumes."
       << " If not specified, then the min and max data" << endl
       << " values will be used when reading the data into memory." << endl;
  cout << "                           Format: low high" << endl;

  cout << endl;
  cout << "    -tfc | --tf-color --> Specify the next color to in the transfer"
       << " function for volumes. Each entry will add to the total list of"
       << " colors in the order they are specified." << endl;
  cout << "                              Format: R G B A" << endl;
  cout << "                         Value Range: [0,1]" << endl;

  cout << "    -tfs | --tf-scale --> Specify the opacity the transfer function"
       << " will scale to: [0,x] where x is the input value." << endl;
  cout << "                          default: 1.0" << endl;

  cout << "    -tff | --tf-file --> Specify the transfer function file to use"
       << endl;

  cout << endl;
  cout << "    -is | --surface --> Specify an isosurface at value: val "
       << endl;

  cout << endl;
  cout << "    --help --> Print this help text" << endl;

  exit(0);
}

void parseCommandLine(int argc, const char *argv[])
{
  if (argc <= 1) {
    printUsageAndExit();
  }

  for (int i = 1; i < argc; ++i) {
    string arg = argv[i];
    if (arg == "--help") {
      printUsageAndExit();
    } else if (arg == "-i" || arg == "--image") {
      OSPRayFixture::imageOutputFile = argv[++i];
    } else if (arg == "-w" || arg == "--width") {
      OSPRayFixture::width = atoi(argv[++i]);
    } else if (arg == "-h" || arg == "--height") {
      OSPRayFixture::height = atoi(argv[++i]);
    } else if (arg == "-wf" || arg == "--warmup") {
      OSPRayFixture::numWarmupFrames = atoi(argv[++i]);
    } else if (arg == "-bf" || arg == "--bench") {
      OSPRayFixture::numBenchFrames = atoi(argv[++i]);
    } else if (arg == "-bg" || arg == "--background") {
      ospcommon::vec3f &color = OSPRayFixture::bg_color;
      color.x = atof(argv[++i]);
      color.y = atof(argv[++i]);
      color.z = atof(argv[++i]);
    } else if (arg == "-lft" || arg == "--log-frame-times") {
      OSPRayFixture::logFrameTimes = true;
    }
  }

  auto ospObjs = parseWithDefaultParsers(argc, argv);

  ospcommon::box3f bbox;
  std::tie(bbox,
           *OSPRayFixture::model,
           *OSPRayFixture::renderer,
           *OSPRayFixture::camera) = ospObjs;

  float width  = OSPRayFixture::width;
  float height = OSPRayFixture::height;
  auto &camera = *OSPRayFixture::camera;
  camera.set("aspect", width/height);
  camera.commit();
}

void allocateFixtureObjects()
{
  // NOTE(jda) - Have to allocate objects here, because we can't allocate them
  //             statically (before ospInit) and can't in the fixture's
  //             constructor because they need to exist during parseCommandLine.
  OSPRayFixture::renderer = make_unique<ospray::cpp::Renderer>();
  OSPRayFixture::camera   = make_unique<ospray::cpp::Camera>();
  OSPRayFixture::model    = make_unique<ospray::cpp::Model>();
  OSPRayFixture::fb       = make_unique<ospray::cpp::FrameBuffer>();
}

int main(int argc, const char *argv[])
{
  ospInit(&argc, argv);
  allocateFixtureObjects();
  parseCommandLine(argc, argv);

  using namespace std::chrono;
  auto bencher = pico_bench::Benchmarker<milliseconds>{OSPRayFixture::numBenchFrames};

  OSPRayFixture fixture;
  fixture.SetUp();
  auto stats = bencher([&]() {
    fixture.renderer->renderFrame(*fixture.fb, OSP_FB_COLOR | OSP_FB_ACCUM);
  });
  stats.time_suffix = "ms";
  if (OSPRayFixture::logFrameTimes) {
    for (size_t i = 0; i < stats.size(); ++i) {
      std::cout << stats[i].count() << stats.time_suffix << "\n";
    }
  }
  std::cout << stats << "\n";
  return 0;
}
<commit_msg>Use a double-precision representation for sub-ms time values<commit_after>// ======================================================================== //
// Copyright 2016 Intel Corporation                                         //
//                                                                          //
// 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 <chrono>

#include "OSPRayFixture.h"

#include "commandline/Utility.h"
#include "pico_bench/pico_bench.h"

using std::cout;
using std::endl;
using std::string;

// NOTE(jda) - Implement make_unique() as it didn't show up until C++14...
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique(Args&& ...args)
{
  return std::unique_ptr<T>(new T( std::forward<Args>(args)... ));
}

void printUsageAndExit()
{
  cout << "Usage: ospBenchmark [options] model_file" << endl;

  cout << endl << "Args:" << endl;

  cout << endl;
  cout << "    model_file --> Scene used for benchmarking, supported types"
            << " are:" << endl;
  cout << "                   stl, msg, tri, xml, obj, hbp, x3d" << endl;

  cout << endl;
  cout << "Options:" << endl;

  cout << endl;
  cout << "**generic rendering options**" << endl;

  cout << endl;
  cout << "    -i | --image --> Specify the base filename to write the"
       << " framebuffer to a file." << endl;
  cout << "                     If ommitted, no file will be written." << endl;
  cout << "                     NOTE: this option adds '.ppm' to the end of the"
       << " filename" << endl;

  cout << endl;
  cout << "    -w | --width --> Specify the width of the benchmark frame"
       << endl;
  cout << "                     default: 1024" << endl;

  cout << endl;
  cout << "    -h | --height --> Specify the height of the benchmark frame"
       << endl;
  cout << "                      default: 1024" << endl;

  cout << endl;
  cout << "    -r | --renderer --> Specify the renderer to be benchmarked."
       << endl;
  cout << "                        Ex: -r pathtracer" << endl;
  cout << "                        default: ao1" << endl;

  cout << endl;
  cout << "    -bg | --background --> Specify the background color: R G B"
       << endl;

  cout << endl;
  cout << "    -wf | --warmup --> Specify the number of warmup frames: N"
       << endl;
  cout << "                       default: 10" << endl;

  cout << endl;
  cout << "    -bf | --bench --> Specify the number of benchmark frames: N"
       << endl;
  cout << "                      default: 100" << endl;

  cout << endl;
  cout << "    -lft | --log-frame-times --> Log frame time in ms for every frame rendered"
       << endl;

  cout << endl;
  cout << "**camera rendering options**" << endl;

  cout << endl;
  cout << "    -vp | --eye --> Specify the camera eye as: ex ey ez " << endl;

  cout << endl;
  cout << "    -vi | --gaze --> Specify the camera gaze point as: ix iy iz "
       << endl;

  cout << endl;
  cout << "    -vu | --up --> Specify the camera up as: ux uy uz " << endl;

  cout << endl;
  cout << "**volume rendering options**" << endl;

  cout << endl;
  cout << "    -s | --sampling-rate --> Specify the sampling rate for volumes."
       << endl;
  cout << "                             default: 0.125" << endl;

  cout << endl;
  cout << "    -dr | --data-range --> Specify the data range for volumes."
       << " If not specified, then the min and max data" << endl
       << " values will be used when reading the data into memory." << endl;
  cout << "                           Format: low high" << endl;

  cout << endl;
  cout << "    -tfc | --tf-color --> Specify the next color to in the transfer"
       << " function for volumes. Each entry will add to the total list of"
       << " colors in the order they are specified." << endl;
  cout << "                              Format: R G B A" << endl;
  cout << "                         Value Range: [0,1]" << endl;

  cout << "    -tfs | --tf-scale --> Specify the opacity the transfer function"
       << " will scale to: [0,x] where x is the input value." << endl;
  cout << "                          default: 1.0" << endl;

  cout << "    -tff | --tf-file --> Specify the transfer function file to use"
       << endl;

  cout << endl;
  cout << "    -is | --surface --> Specify an isosurface at value: val "
       << endl;

  cout << endl;
  cout << "    --help --> Print this help text" << endl;

  exit(0);
}

void parseCommandLine(int argc, const char *argv[])
{
  if (argc <= 1) {
    printUsageAndExit();
  }

  for (int i = 1; i < argc; ++i) {
    string arg = argv[i];
    if (arg == "--help") {
      printUsageAndExit();
    } else if (arg == "-i" || arg == "--image") {
      OSPRayFixture::imageOutputFile = argv[++i];
    } else if (arg == "-w" || arg == "--width") {
      OSPRayFixture::width = atoi(argv[++i]);
    } else if (arg == "-h" || arg == "--height") {
      OSPRayFixture::height = atoi(argv[++i]);
    } else if (arg == "-wf" || arg == "--warmup") {
      OSPRayFixture::numWarmupFrames = atoi(argv[++i]);
    } else if (arg == "-bf" || arg == "--bench") {
      OSPRayFixture::numBenchFrames = atoi(argv[++i]);
    } else if (arg == "-bg" || arg == "--background") {
      ospcommon::vec3f &color = OSPRayFixture::bg_color;
      color.x = atof(argv[++i]);
      color.y = atof(argv[++i]);
      color.z = atof(argv[++i]);
    } else if (arg == "-lft" || arg == "--log-frame-times") {
      OSPRayFixture::logFrameTimes = true;
    }
  }

  auto ospObjs = parseWithDefaultParsers(argc, argv);

  ospcommon::box3f bbox;
  std::tie(bbox,
           *OSPRayFixture::model,
           *OSPRayFixture::renderer,
           *OSPRayFixture::camera) = ospObjs;

  float width  = OSPRayFixture::width;
  float height = OSPRayFixture::height;
  auto &camera = *OSPRayFixture::camera;
  camera.set("aspect", width/height);
  camera.commit();
}

void allocateFixtureObjects()
{
  // NOTE(jda) - Have to allocate objects here, because we can't allocate them
  //             statically (before ospInit) and can't in the fixture's
  //             constructor because they need to exist during parseCommandLine.
  OSPRayFixture::renderer = make_unique<ospray::cpp::Renderer>();
  OSPRayFixture::camera   = make_unique<ospray::cpp::Camera>();
  OSPRayFixture::model    = make_unique<ospray::cpp::Model>();
  OSPRayFixture::fb       = make_unique<ospray::cpp::FrameBuffer>();
}

int main(int argc, const char *argv[])
{
  ospInit(&argc, argv);
  allocateFixtureObjects();
  parseCommandLine(argc, argv);

  using namespace std::chrono;
  using Millis = duration<double, std::ratio<1, 1000>>;
  auto bencher = pico_bench::Benchmarker<Millis>{OSPRayFixture::numBenchFrames};

  OSPRayFixture fixture;
  fixture.SetUp();
  auto stats = bencher([&]() {
    fixture.renderer->renderFrame(*fixture.fb, OSP_FB_COLOR | OSP_FB_ACCUM);
  });
  stats.time_suffix = "ms";
  if (OSPRayFixture::logFrameTimes) {
    for (size_t i = 0; i < stats.size(); ++i) {
      std::cout << stats[i].count() << stats.time_suffix << "\n";
    }
  }
  std::cout << stats << "\n";
  return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2020 mogemimi. Distributed under the MIT license.

#include "AudioEngineXAudio2.hpp"
#include "Pomdog/Math/MathHelper.hpp"
#include "Pomdog/Utility/Assert.hpp"
#include "Pomdog/Utility/Exception.hpp"

#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && !defined(__cplusplus_winrt)
#include <Windows.Devices.Enumeration.h>
#include <Windows.Foundation.Collections.h>
#include <wrl/client.h>
#include <wrl/event.h>
#include <wrl/wrappers/corewrappers.h>
#pragma comment(lib, "runtimeobject.lib")
#endif

#include <algorithm>
#include <string>
#include <utility>
#include <vector>

namespace Pomdog::Detail::SoundSystem::XAudio2 {
namespace {

std::string GetErrorDesc(HRESULT hr, const std::string& desc)
{
    return "Failed to call " + desc + ", HRESULT=" + std::to_string(hr);
}

#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)

struct AudioDeviceDetails {
    std::wstring DeviceID;
    std::wstring DisplayName;
    bool IsDefault = false;
    bool IsEnabled = false;
};

std::vector<AudioDeviceDetails> EnumerateAudioDevices()
{
#if defined(_XBOX_ONE)
    ///@todo Not implemented
#elif (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && defined(__cplusplus_winrt)
    ///@todo Not implemented

    //using Windows::Devices::Enumeration::DeviceClass;
    //using Windows::Devices::Enumeration::DeviceInformation;
    //using Windows::Devices::Enumeration::DeviceInformationCollection;

    //auto operation = DeviceInformation::FindAllAsync(DeviceClass::AudioRender);
    //while (operation->Status != Windows::Foundation::AsyncStatus::Completed);

    //DeviceInformationCollection^ devices = operation->GetResults();

    //for (unsigned int index = 0; index < devices->Size; ++index)
    //{
    //    using Windows::Devices::Enumeration::DeviceInformation;
    //    DeviceInformation^ deviceInfo = devices->GetAt(index);
    //    //deviceInfo->Name->Data();
    //    //deviceInfo->Id->Data();
    //}

#elif (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && !defined(__cplusplus_winrt)

    using Microsoft::WRL::Callback;
    using Microsoft::WRL::ComPtr;
    using namespace Microsoft::WRL::Wrappers;
    using namespace ABI::Windows::Foundation;
    using namespace ABI::Windows::Foundation::Collections;
    using namespace ABI::Windows::Devices::Enumeration;

    RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
    HRESULT hr = initialize;

    if (FAILED(hr)) {
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "RoInitialize"));
    }

    ComPtr<IDeviceInformationStatics> deviceInfomationFactory;
    hr = GetActivationFactory(HStringReference(
        RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(), &deviceInfomationFactory);

    if (FAILED(hr)) {
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "GetActivationFactory"));
    }

    Event findCompleted(CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS));

    if (!findCompleted.IsValid()) {
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "CreateEventEx"));
    }

    ComPtr<IAsyncOperation<DeviceInformationCollection*>> findOperation;
    hr = deviceInfomationFactory->FindAllAsyncDeviceClass(DeviceClass_AudioRender, findOperation.GetAddressOf());

    if (FAILED(hr)) {
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "FindAllAsyncDeviceClass"));
    }

    auto callback = Callback<IAsyncOperationCompletedHandler<DeviceInformationCollection*>>(
        [&findCompleted](IAsyncOperation<DeviceInformationCollection*>*, AsyncStatus) -> HRESULT {
            SetEvent(findCompleted.Get());
            return S_OK;
        });

    findOperation->put_Completed(callback.Get());

    WaitForSingleObjectEx(findCompleted.Get(), INFINITE, FALSE);

    ComPtr<IVectorView<DeviceInformation*>> devices;
    findOperation->GetResults(devices.GetAddressOf());

    unsigned int count = 0;
    hr = devices->get_Size(&count);

    if (FAILED(hr)) {
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "get_Size"));
    }

    if (count <= 0) {
        return {};
    }

    std::vector<AudioDeviceDetails> result;

    POMDOG_ASSERT(count >= 1);
    result.reserve(count);

    for (unsigned int index = 0; index < count; ++index) {
        ComPtr<IDeviceInformation> deviceInfo;
        hr = devices->GetAt(index, deviceInfo.GetAddressOf());

        if (FAILED(hr)) {
            continue;
        }

        HString id;
        deviceInfo->get_Id(id.GetAddressOf());
        HString name;
        deviceInfo->get_Name(name.GetAddressOf());

        AudioDeviceDetails deviceDetails;
        deviceDetails.DeviceID = id.GetRawBuffer(nullptr);
        deviceDetails.DisplayName = name.GetRawBuffer(nullptr);
        deviceDetails.IsDefault = false;
        deviceDetails.IsEnabled = false;

        {
            ::boolean isDefault;
            if (SUCCEEDED(deviceInfo->get_IsDefault(&isDefault))) {
                deviceDetails.IsDefault = (isDefault == TRUE);
            }
        }
        {
            ::boolean isEnabled;
            if (SUCCEEDED(deviceInfo->get_IsEnabled(&isEnabled))) {
                deviceDetails.IsEnabled = (isEnabled == TRUE);
            }
        }

        result.push_back(std::move(deviceDetails));
    }

    std::sort(std::begin(result), std::end(result), [](const auto& a, const auto& b) {
        int priorityA = (a.IsEnabled ? 0b01 : 0) & (a.IsDefault ? 0b10 : 0);
        int priorityB = (b.IsEnabled ? 0b01 : 0) & (b.IsDefault ? 0b10 : 0);
        return priorityA > priorityB;
    });

    return std::move(result);
#endif
}
#endif

} // namespace

AudioEngineXAudio2::AudioEngineXAudio2()
    : masteringVoice(nullptr)
{
    HRESULT hr = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
    if (FAILED(hr)) {
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "CoInitializeEx"));
    }

    UINT32 flags = 0;
#if defined(DEBUG) && !defined(NDEBUG)
    flags |= XAUDIO2_DEBUG_ENGINE;
#endif

    hr = ::XAudio2Create(&xAudio2, flags, XAUDIO2_DEFAULT_PROCESSOR);
    if (FAILED(hr)) {
        ::CoUninitialize();
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "XAudio2Create"));
    }

#if defined(DEBUG) && !defined(NDEBUG)
    {
        XAUDIO2_DEBUG_CONFIGURATION debugConfig;
        debugConfig.TraceMask = XAUDIO2_LOG_ERRORS | XAUDIO2_LOG_WARNINGS;
        debugConfig.BreakMask = 0;
        debugConfig.LogThreadID = FALSE;
        debugConfig.LogFileline = FALSE;
        debugConfig.LogFunctionName = FALSE;
        debugConfig.LogTiming = FALSE;

        POMDOG_ASSERT(xAudio2);
        xAudio2->SetDebugConfiguration(&debugConfig, 0);
    }
#endif

    std::vector<AudioDeviceDetails> audioDevices;

    try {
        audioDevices = EnumerateAudioDevices();
    }
    catch (const std::exception& e) {
        xAudio2.Reset();
        ::CoUninitialize();
        throw e;
    }

    wchar_t* deviceID = nullptr;

#if 0
    if (audioDevices.empty()) {
        xAudio2.Reset();
        ::CoUninitialize();
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "XAudio2Create"));
    }
    POMDOG_ASSERT(!audioDevices.empty());

    deviceID = audioDevices.front().DeviceID.data();
#endif

    hr = xAudio2->CreateMasteringVoice(&masteringVoice, XAUDIO2_DEFAULT_CHANNELS,
        XAUDIO2_DEFAULT_SAMPLERATE, 0, deviceID, nullptr, AudioCategory_GameEffects);

    if (FAILED(hr)) {
        xAudio2.Reset();
        ::CoUninitialize();
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "CreateMasteringVoice"));
    }
}

AudioEngineXAudio2::~AudioEngineXAudio2()
{
    if (masteringVoice) {
        masteringVoice->DestroyVoice();
        masteringVoice = nullptr;
    }

    if (xAudio2) {
        xAudio2.Reset();
        ::CoUninitialize();
    }
}

float AudioEngineXAudio2::GetMasterVolume() const
{
    float volume = 0;
    if (xAudio2 && masteringVoice != nullptr) {
        masteringVoice->GetVolume(&volume);
    }
    return volume;
}

void AudioEngineXAudio2::SetMasterVolume(float volumeIn)
{
    if (xAudio2 && masteringVoice != nullptr) {
        masteringVoice->SetVolume(MathHelper::Saturate(volumeIn), XAUDIO2_COMMIT_NOW);
    }
}

IXAudio2* AudioEngineXAudio2::XAudio2Engine() const
{
    POMDOG_ASSERT(xAudio2);
    return xAudio2.Get();
}

} // namespace Pomdog::Detail::SoundSystem::XAudio2
<commit_msg>Fix debug flags for latest XAudio2 API<commit_after>// Copyright (c) 2013-2020 mogemimi. Distributed under the MIT license.

#include "AudioEngineXAudio2.hpp"
#include "Pomdog/Math/MathHelper.hpp"
#include "Pomdog/Utility/Assert.hpp"
#include "Pomdog/Utility/Exception.hpp"

#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && !defined(__cplusplus_winrt)
#include <Windows.Devices.Enumeration.h>
#include <Windows.Foundation.Collections.h>
#include <wrl/client.h>
#include <wrl/event.h>
#include <wrl/wrappers/corewrappers.h>
#pragma comment(lib, "runtimeobject.lib")
#endif

#include <algorithm>
#include <string>
#include <utility>
#include <vector>

namespace Pomdog::Detail::SoundSystem::XAudio2 {
namespace {

std::string GetErrorDesc(HRESULT hr, const std::string& desc)
{
    return "Failed to call " + desc + ", HRESULT=" + std::to_string(hr);
}

#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)

struct AudioDeviceDetails {
    std::wstring DeviceID;
    std::wstring DisplayName;
    bool IsDefault = false;
    bool IsEnabled = false;
};

std::vector<AudioDeviceDetails> EnumerateAudioDevices()
{
#if defined(_XBOX_ONE)
    ///@todo Not implemented
#elif (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && defined(__cplusplus_winrt)
    ///@todo Not implemented

    //using Windows::Devices::Enumeration::DeviceClass;
    //using Windows::Devices::Enumeration::DeviceInformation;
    //using Windows::Devices::Enumeration::DeviceInformationCollection;

    //auto operation = DeviceInformation::FindAllAsync(DeviceClass::AudioRender);
    //while (operation->Status != Windows::Foundation::AsyncStatus::Completed);

    //DeviceInformationCollection^ devices = operation->GetResults();

    //for (unsigned int index = 0; index < devices->Size; ++index)
    //{
    //    using Windows::Devices::Enumeration::DeviceInformation;
    //    DeviceInformation^ deviceInfo = devices->GetAt(index);
    //    //deviceInfo->Name->Data();
    //    //deviceInfo->Id->Data();
    //}

#elif (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && !defined(__cplusplus_winrt)

    using Microsoft::WRL::Callback;
    using Microsoft::WRL::ComPtr;
    using namespace Microsoft::WRL::Wrappers;
    using namespace ABI::Windows::Foundation;
    using namespace ABI::Windows::Foundation::Collections;
    using namespace ABI::Windows::Devices::Enumeration;

    RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
    HRESULT hr = initialize;

    if (FAILED(hr)) {
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "RoInitialize"));
    }

    ComPtr<IDeviceInformationStatics> deviceInfomationFactory;
    hr = GetActivationFactory(HStringReference(
        RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(), &deviceInfomationFactory);

    if (FAILED(hr)) {
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "GetActivationFactory"));
    }

    Event findCompleted(CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS));

    if (!findCompleted.IsValid()) {
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "CreateEventEx"));
    }

    ComPtr<IAsyncOperation<DeviceInformationCollection*>> findOperation;
    hr = deviceInfomationFactory->FindAllAsyncDeviceClass(DeviceClass_AudioRender, findOperation.GetAddressOf());

    if (FAILED(hr)) {
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "FindAllAsyncDeviceClass"));
    }

    auto callback = Callback<IAsyncOperationCompletedHandler<DeviceInformationCollection*>>(
        [&findCompleted](IAsyncOperation<DeviceInformationCollection*>*, AsyncStatus) -> HRESULT {
            SetEvent(findCompleted.Get());
            return S_OK;
        });

    findOperation->put_Completed(callback.Get());

    WaitForSingleObjectEx(findCompleted.Get(), INFINITE, FALSE);

    ComPtr<IVectorView<DeviceInformation*>> devices;
    findOperation->GetResults(devices.GetAddressOf());

    unsigned int count = 0;
    hr = devices->get_Size(&count);

    if (FAILED(hr)) {
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "get_Size"));
    }

    if (count <= 0) {
        return {};
    }

    std::vector<AudioDeviceDetails> result;

    POMDOG_ASSERT(count >= 1);
    result.reserve(count);

    for (unsigned int index = 0; index < count; ++index) {
        ComPtr<IDeviceInformation> deviceInfo;
        hr = devices->GetAt(index, deviceInfo.GetAddressOf());

        if (FAILED(hr)) {
            continue;
        }

        HString id;
        deviceInfo->get_Id(id.GetAddressOf());
        HString name;
        deviceInfo->get_Name(name.GetAddressOf());

        AudioDeviceDetails deviceDetails;
        deviceDetails.DeviceID = id.GetRawBuffer(nullptr);
        deviceDetails.DisplayName = name.GetRawBuffer(nullptr);
        deviceDetails.IsDefault = false;
        deviceDetails.IsEnabled = false;

        {
            ::boolean isDefault;
            if (SUCCEEDED(deviceInfo->get_IsDefault(&isDefault))) {
                deviceDetails.IsDefault = (isDefault == TRUE);
            }
        }
        {
            ::boolean isEnabled;
            if (SUCCEEDED(deviceInfo->get_IsEnabled(&isEnabled))) {
                deviceDetails.IsEnabled = (isEnabled == TRUE);
            }
        }

        result.push_back(std::move(deviceDetails));
    }

    std::sort(std::begin(result), std::end(result), [](const auto& a, const auto& b) {
        int priorityA = (a.IsEnabled ? 0b01 : 0) & (a.IsDefault ? 0b10 : 0);
        int priorityB = (b.IsEnabled ? 0b01 : 0) & (b.IsDefault ? 0b10 : 0);
        return priorityA > priorityB;
    });

    return std::move(result);
#endif
}
#endif

} // namespace

AudioEngineXAudio2::AudioEngineXAudio2()
    : masteringVoice(nullptr)
{
    HRESULT hr = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
    if (FAILED(hr)) {
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "CoInitializeEx"));
    }

#if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) && defined(DEBUG) && !defined(NDEBUG)
    constexpr UINT32 flags = XAUDIO2_DEBUG_ENGINE;
#else
    // NOTE: The debugging facilities are always available for XAudio2 in Windows 8 and newer.
    constexpr UINT32 flags = 0;
#endif

    hr = ::XAudio2Create(&xAudio2, flags, XAUDIO2_DEFAULT_PROCESSOR);
    if (FAILED(hr)) {
        ::CoUninitialize();
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "XAudio2Create"));
    }

#if defined(DEBUG) && !defined(NDEBUG)
    {
        XAUDIO2_DEBUG_CONFIGURATION debugConfig;
        debugConfig.TraceMask = XAUDIO2_LOG_ERRORS | XAUDIO2_LOG_WARNINGS;
        debugConfig.BreakMask = 0;
        debugConfig.LogThreadID = FALSE;
        debugConfig.LogFileline = FALSE;
        debugConfig.LogFunctionName = FALSE;
        debugConfig.LogTiming = FALSE;

        POMDOG_ASSERT(xAudio2);
        xAudio2->SetDebugConfiguration(&debugConfig, 0);
    }
#endif

    std::vector<AudioDeviceDetails> audioDevices;

    try {
        audioDevices = EnumerateAudioDevices();
    }
    catch (const std::exception& e) {
        xAudio2.Reset();
        ::CoUninitialize();
        throw e;
    }

    wchar_t* deviceID = nullptr;

#if 0
    if (audioDevices.empty()) {
        xAudio2.Reset();
        ::CoUninitialize();
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "XAudio2Create"));
    }
    POMDOG_ASSERT(!audioDevices.empty());

    deviceID = audioDevices.front().DeviceID.data();
#endif

    hr = xAudio2->CreateMasteringVoice(&masteringVoice, XAUDIO2_DEFAULT_CHANNELS,
        XAUDIO2_DEFAULT_SAMPLERATE, 0, deviceID, nullptr, AudioCategory_GameEffects);

    if (FAILED(hr)) {
        xAudio2.Reset();
        ::CoUninitialize();
        POMDOG_THROW_EXCEPTION(std::runtime_error, GetErrorDesc(hr, "CreateMasteringVoice"));
    }
}

AudioEngineXAudio2::~AudioEngineXAudio2()
{
    if (masteringVoice) {
        masteringVoice->DestroyVoice();
        masteringVoice = nullptr;
    }

    if (xAudio2) {
        xAudio2.Reset();
        ::CoUninitialize();
    }
}

float AudioEngineXAudio2::GetMasterVolume() const
{
    float volume = 0;
    if (xAudio2 && masteringVoice != nullptr) {
        masteringVoice->GetVolume(&volume);
    }
    return volume;
}

void AudioEngineXAudio2::SetMasterVolume(float volumeIn)
{
    if (xAudio2 && masteringVoice != nullptr) {
        masteringVoice->SetVolume(MathHelper::Saturate(volumeIn), XAUDIO2_COMMIT_NOW);
    }
}

IXAudio2* AudioEngineXAudio2::XAudio2Engine() const
{
    POMDOG_ASSERT(xAudio2);
    return xAudio2.Get();
}

} // namespace Pomdog::Detail::SoundSystem::XAudio2
<|endoftext|>


<commit_before>/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *    All rights reserved.
 *
 *    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 <controller/CommissioningDelegate.h>

namespace chip {
namespace Controller {

const char * StageToString(CommissioningStage stage)
{
    switch (stage)
    {
    case kError:
        return "Error";
        break;

    case kSecurePairing:
        return "SecurePairing";
        break;

    case kArmFailsafe:
        return "ArmFailSafe";
        break;

    case kConfigRegulatory:
        return "ConfigRegulatory";
        break;

    case kSendPAICertificateRequest:
        return "SendPAICertificateRequest";
        break;

    case kSendDACCertificateRequest:
        return "SendDACCertificateRequest";
        break;

    case kSendAttestationRequest:
        return "SendAttestationRequest";
        break;

    case kAttestationVerification:
        return "AttestationVerification";
        break;

    case kSendOpCertSigningRequest:
        return "SendOpCertSigningRequest";
        break;

    case kGenerateNOCChain:
        return "GenerateNOCChain";
        break;

    case kSendTrustedRootCert:
        return "SendTrustedRootCert";
        break;

    case kSendNOC:
        return "SendNOC";
        break;

    case kWiFiNetworkSetup:
        return "WiFiNetworkSetup";
        break;

    case kThreadNetworkSetup:
        return "ThreadNetworkSetup";
        break;

    case kWiFiNetworkEnable:
        return "WiFiNetworkEnable";
        break;

    case kThreadNetworkEnable:
        return "ThreadNetworkEnable";
        break;

    case kFindOperational:
        return "FindOperational";
        break;

    case kSendComplete:
        return "SendComplete";
        break;

    case kCleanup:
        return "Cleanup";
        break;

    default:
        return "???";
        break;
    }
}

} // namespace Controller
} // namespace chip
<commit_msg>Adding missing commissioning stage string. (#16471)<commit_after>/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *    All rights reserved.
 *
 *    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 <controller/CommissioningDelegate.h>

namespace chip {
namespace Controller {

const char * StageToString(CommissioningStage stage)
{
    switch (stage)
    {
    case kError:
        return "Error";
        break;

    case kSecurePairing:
        return "SecurePairing";
        break;

    case kReadCommissioningInfo:
        return "ReadCommissioningInfo";
        break;

    case kArmFailsafe:
        return "ArmFailSafe";
        break;

    case kConfigRegulatory:
        return "ConfigRegulatory";
        break;

    case kSendPAICertificateRequest:
        return "SendPAICertificateRequest";
        break;

    case kSendDACCertificateRequest:
        return "SendDACCertificateRequest";
        break;

    case kSendAttestationRequest:
        return "SendAttestationRequest";
        break;

    case kAttestationVerification:
        return "AttestationVerification";
        break;

    case kSendOpCertSigningRequest:
        return "SendOpCertSigningRequest";
        break;

    case kGenerateNOCChain:
        return "GenerateNOCChain";
        break;

    case kSendTrustedRootCert:
        return "SendTrustedRootCert";
        break;

    case kSendNOC:
        return "SendNOC";
        break;

    case kWiFiNetworkSetup:
        return "WiFiNetworkSetup";
        break;

    case kThreadNetworkSetup:
        return "ThreadNetworkSetup";
        break;

    case kWiFiNetworkEnable:
        return "WiFiNetworkEnable";
        break;

    case kThreadNetworkEnable:
        return "ThreadNetworkEnable";
        break;

    case kFindOperational:
        return "FindOperational";
        break;

    case kSendComplete:
        return "SendComplete";
        break;

    case kCleanup:
        return "Cleanup";
        break;

    default:
        return "???";
        break;
    }
}

} // namespace Controller
} // namespace chip
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2016 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 "src/cpp/thread_manager/thread_manager.h"

#include <climits>
#include <mutex>

#include <grpc/support/log.h>
#include "src/core/lib/gprpp/thd.h"
#include "src/core/lib/iomgr/exec_ctx.h"

namespace grpc {

ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr)
    : thd_mgr_(thd_mgr) {
  // Make thread creation exclusive with respect to its join happening in
  // ~WorkerThread().
  thd_ = grpc_core::Thread(
      "grpcpp_sync_server",
      [](void* th) { static_cast<ThreadManager::WorkerThread*>(th)->Run(); },
      this,
      &created_
      );
  if (!created_) {
    gpr_log(GPR_ERROR,
            "Could not create grpc_sync_server worker-thread"
            );
  } else {
    thd_.Start();
  }
}

void ThreadManager::WorkerThread::Run() {
  thd_mgr_->MainWorkLoop();
  thd_mgr_->MarkAsCompleted(this);
}

ThreadManager::WorkerThread::~WorkerThread() {
  // Don't join until the thread is fully constructed.
  thd_.Join();
}

ThreadManager::ThreadManager(const char* name,
                             grpc_resource_quota* resource_quota,
                             int min_pollers, int max_pollers)
    : shutdown_(false),
      num_pollers_(0),
      min_pollers_(min_pollers),
      max_pollers_(max_pollers == -1 ? INT_MAX : max_pollers),
      num_threads_(0),
      max_active_threads_sofar_(0) {
  resource_user_ = grpc_resource_user_create(resource_quota, name);
}

ThreadManager::~ThreadManager() {
  {
    grpc_core::MutexLock lock(&mu_);
    GPR_ASSERT(num_threads_ == 0);
  }

  grpc_core::ExecCtx exec_ctx;  // grpc_resource_user_unref needs an exec_ctx
  grpc_resource_user_unref(resource_user_);
  CleanupCompletedThreads();
}

void ThreadManager::Wait() {
  grpc_core::MutexLock lock(&mu_);
  while (num_threads_ != 0) {
    shutdown_cv_.Wait(&mu_);
  }
}

void ThreadManager::Shutdown() {
  grpc_core::MutexLock lock(&mu_);
  shutdown_ = true;
}

bool ThreadManager::IsShutdown() {
  grpc_core::MutexLock lock(&mu_);
  return shutdown_;
}

int ThreadManager::GetMaxActiveThreadsSoFar() {
  grpc_core::MutexLock list_lock(&list_mu_);
  return max_active_threads_sofar_;
}

void ThreadManager::MarkAsCompleted(WorkerThread* thd) {
  {
    grpc_core::MutexLock list_lock(&list_mu_);
    completed_threads_.push_back(thd);
  }

  {
    grpc_core::MutexLock lock(&mu_);
    num_threads_--;
    if (num_threads_ == 0) {
      shutdown_cv_.Signal();
    }
  }

  // Give a thread back to the resource quota
  grpc_resource_user_free_threads(resource_user_, 1);
}

void ThreadManager::CleanupCompletedThreads() {
  std::list<WorkerThread*> completed_threads;
  {
    // swap out the completed threads list: allows other threads to clean up
    // more quickly
    grpc_core::MutexLock lock(&list_mu_);
    completed_threads.swap(completed_threads_);
  }
  for (auto thd : completed_threads) delete thd;
}

void ThreadManager::Initialize() {
  if (!grpc_resource_user_allocate_threads(resource_user_, min_pollers_)) {
    gpr_log(GPR_ERROR,
            "No thread quota available to even create the minimum required "
            "polling threads (i.e %d). Unable to start the thread manager",
            min_pollers_);
    abort();
  }

  {
    grpc_core::MutexLock lock(&mu_);
    num_pollers_ = min_pollers_;
    num_threads_ = min_pollers_;
    max_active_threads_sofar_ = min_pollers_;
  }

  for (int i = 0; i < min_pollers_; i++) {
    new WorkerThread(this);
  }
}

void ThreadManager::MainWorkLoop() {
  while (true) {
    void* tag;
    bool ok;
    WorkStatus work_status = PollForWork(&tag, &ok);

    grpc_core::ReleasableMutexLock lock(&mu_);
    // Reduce the number of pollers by 1 and check what happened with the poll
    num_pollers_--;
    bool done = false;
    switch (work_status) {
      case TIMEOUT:
        // If we timed out and we have more pollers than we need (or we are
        // shutdown), finish this thread
        if (shutdown_ || num_pollers_ > max_pollers_) done = true;
        break;
      case SHUTDOWN:
        // If the thread manager is shutdown, finish this thread
        done = true;
        break;
      case WORK_FOUND:
        // If we got work and there are now insufficient pollers and there is
        // quota available to create a new thread, start a new poller thread
        bool resource_exhausted = false;
        if (!shutdown_ && num_pollers_ < min_pollers_) {
          if (grpc_resource_user_allocate_threads(resource_user_, 1)) {
            // We can allocate a new poller thread
            num_pollers_++;
            num_threads_++;
            if (num_threads_ > max_active_threads_sofar_) {
              max_active_threads_sofar_ = num_threads_;
            }
            // Drop lock before spawning thread to avoid contention
            lock.Unlock();
            WorkerThread* w = new WorkerThread(this);
            if (!w->created()) {
              num_pollers_--;
              num_threads_--;
              resource_exhausted = true;
            }
          } else if (num_pollers_ > 0) {
            // There is still at least some thread polling, so we can go on
            // even though we are below the number of pollers that we would
            // like to have (min_pollers_)
            lock.Unlock();
          } else {
            // There are no pollers to spare and we couldn't allocate
            // a new thread, so resources are exhausted!
            lock.Unlock();
            resource_exhausted = true;
          }
        } else {
          // There are a sufficient number of pollers available so we can do
          // the work and continue polling with our existing poller threads
          lock.Unlock();
        }
        // Lock is always released at this point - do the application work
        // or return resource exhausted if there is new work but we couldn't
        // get a thread in which to do it.
        DoWork(tag, ok, !resource_exhausted);
        // Take the lock again to check post conditions
        lock.Lock();
        // If we're shutdown, we should finish at this point.
        if (shutdown_) done = true;
        break;
    }
    // If we decided to finish the thread, break out of the while loop
    if (done) break;

    // Otherwise go back to polling as long as it doesn't exceed max_pollers_
    //
    // **WARNING**:
    // There is a possibility of threads thrashing here (i.e excessive thread
    // shutdowns and creations than the ideal case). This happens if max_poller_
    // count is small and the rate of incoming requests is also small. In such
    // scenarios we can possibly configure max_pollers_ to a higher value and/or
    // increase the cq timeout.
    //
    // However, not doing this check here and unconditionally incrementing
    // num_pollers (and hoping that the system will eventually settle down) has
    // far worse consequences i.e huge number of threads getting created to the
    // point of thread-exhaustion. For example: if the incoming request rate is
    // very high, all the polling threads will return very quickly from
    // PollForWork() with WORK_FOUND. They all briefly decrement num_pollers_
    // counter thereby possibly - and briefly - making it go below min_pollers;
    // This will most likely result in the creation of a new poller since
    // num_pollers_ dipped below min_pollers_.
    //
    // Now, If we didn't do the max_poller_ check here, all these threads will
    // go back to doing PollForWork() and the whole cycle repeats (with a new
    // thread being added in each cycle). Once the total number of threads in
    // the system crosses a certain threshold (around ~1500), there is heavy
    // contention on mutexes (the mu_ here or the mutexes in gRPC core like the
    // pollset mutex) that makes DoWork() take longer to finish thereby causing
    // new poller threads to be created even faster. This results in a thread
    // avalanche.
    if (num_pollers_ < max_pollers_) {
      num_pollers_++;
    } else {
      break;
    }
  };

  // This thread is exiting. Do some cleanup work i.e delete already completed
  // worker threads
  CleanupCompletedThreads();

  // If we are here, either ThreadManager is shutting down or it already has
  // enough threads.
}

}  // namespace grpc
<commit_msg>Fix formatting<commit_after>/*
 *
 * Copyright 2016 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 "src/cpp/thread_manager/thread_manager.h"

#include <climits>
#include <mutex>

#include <grpc/support/log.h>
#include "src/core/lib/gprpp/thd.h"
#include "src/core/lib/iomgr/exec_ctx.h"

namespace grpc {

ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr)
    : thd_mgr_(thd_mgr) {
  // Make thread creation exclusive with respect to its join happening in
  // ~WorkerThread().
  thd_ = grpc_core::Thread(
      "grpcpp_sync_server",
      [](void* th) { static_cast<ThreadManager::WorkerThread*>(th)->Run(); },
      this, &created_);
  if (!created_) {
    gpr_log(GPR_ERROR, "Could not create grpc_sync_server worker-thread");
  } else {
    thd_.Start();
  }
}

void ThreadManager::WorkerThread::Run() {
  thd_mgr_->MainWorkLoop();
  thd_mgr_->MarkAsCompleted(this);
}

ThreadManager::WorkerThread::~WorkerThread() {
  // Don't join until the thread is fully constructed.
  thd_.Join();
}

ThreadManager::ThreadManager(const char* name,
                             grpc_resource_quota* resource_quota,
                             int min_pollers, int max_pollers)
    : shutdown_(false),
      num_pollers_(0),
      min_pollers_(min_pollers),
      max_pollers_(max_pollers == -1 ? INT_MAX : max_pollers),
      num_threads_(0),
      max_active_threads_sofar_(0) {
  resource_user_ = grpc_resource_user_create(resource_quota, name);
}

ThreadManager::~ThreadManager() {
  {
    grpc_core::MutexLock lock(&mu_);
    GPR_ASSERT(num_threads_ == 0);
  }

  grpc_core::ExecCtx exec_ctx;  // grpc_resource_user_unref needs an exec_ctx
  grpc_resource_user_unref(resource_user_);
  CleanupCompletedThreads();
}

void ThreadManager::Wait() {
  grpc_core::MutexLock lock(&mu_);
  while (num_threads_ != 0) {
    shutdown_cv_.Wait(&mu_);
  }
}

void ThreadManager::Shutdown() {
  grpc_core::MutexLock lock(&mu_);
  shutdown_ = true;
}

bool ThreadManager::IsShutdown() {
  grpc_core::MutexLock lock(&mu_);
  return shutdown_;
}

int ThreadManager::GetMaxActiveThreadsSoFar() {
  grpc_core::MutexLock list_lock(&list_mu_);
  return max_active_threads_sofar_;
}

void ThreadManager::MarkAsCompleted(WorkerThread* thd) {
  {
    grpc_core::MutexLock list_lock(&list_mu_);
    completed_threads_.push_back(thd);
  }

  {
    grpc_core::MutexLock lock(&mu_);
    num_threads_--;
    if (num_threads_ == 0) {
      shutdown_cv_.Signal();
    }
  }

  // Give a thread back to the resource quota
  grpc_resource_user_free_threads(resource_user_, 1);
}

void ThreadManager::CleanupCompletedThreads() {
  std::list<WorkerThread*> completed_threads;
  {
    // swap out the completed threads list: allows other threads to clean up
    // more quickly
    grpc_core::MutexLock lock(&list_mu_);
    completed_threads.swap(completed_threads_);
  }
  for (auto thd : completed_threads) delete thd;
}

void ThreadManager::Initialize() {
  if (!grpc_resource_user_allocate_threads(resource_user_, min_pollers_)) {
    gpr_log(GPR_ERROR,
            "No thread quota available to even create the minimum required "
            "polling threads (i.e %d). Unable to start the thread manager",
            min_pollers_);
    abort();
  }

  {
    grpc_core::MutexLock lock(&mu_);
    num_pollers_ = min_pollers_;
    num_threads_ = min_pollers_;
    max_active_threads_sofar_ = min_pollers_;
  }

  for (int i = 0; i < min_pollers_; i++) {
    new WorkerThread(this);
  }
}

void ThreadManager::MainWorkLoop() {
  while (true) {
    void* tag;
    bool ok;
    WorkStatus work_status = PollForWork(&tag, &ok);

    grpc_core::ReleasableMutexLock lock(&mu_);
    // Reduce the number of pollers by 1 and check what happened with the poll
    num_pollers_--;
    bool done = false;
    switch (work_status) {
      case TIMEOUT:
        // If we timed out and we have more pollers than we need (or we are
        // shutdown), finish this thread
        if (shutdown_ || num_pollers_ > max_pollers_) done = true;
        break;
      case SHUTDOWN:
        // If the thread manager is shutdown, finish this thread
        done = true;
        break;
      case WORK_FOUND:
        // If we got work and there are now insufficient pollers and there is
        // quota available to create a new thread, start a new poller thread
        bool resource_exhausted = false;
        if (!shutdown_ && num_pollers_ < min_pollers_) {
          if (grpc_resource_user_allocate_threads(resource_user_, 1)) {
            // We can allocate a new poller thread
            num_pollers_++;
            num_threads_++;
            if (num_threads_ > max_active_threads_sofar_) {
              max_active_threads_sofar_ = num_threads_;
            }
            // Drop lock before spawning thread to avoid contention
            lock.Unlock();
            WorkerThread* w = new WorkerThread(this);
            if (!w->created()) {
              num_pollers_--;
              num_threads_--;
              resource_exhausted = true;
            }
          } else if (num_pollers_ > 0) {
            // There is still at least some thread polling, so we can go on
            // even though we are below the number of pollers that we would
            // like to have (min_pollers_)
            lock.Unlock();
          } else {
            // There are no pollers to spare and we couldn't allocate
            // a new thread, so resources are exhausted!
            lock.Unlock();
            resource_exhausted = true;
          }
        } else {
          // There are a sufficient number of pollers available so we can do
          // the work and continue polling with our existing poller threads
          lock.Unlock();
        }
        // Lock is always released at this point - do the application work
        // or return resource exhausted if there is new work but we couldn't
        // get a thread in which to do it.
        DoWork(tag, ok, !resource_exhausted);
        // Take the lock again to check post conditions
        lock.Lock();
        // If we're shutdown, we should finish at this point.
        if (shutdown_) done = true;
        break;
    }
    // If we decided to finish the thread, break out of the while loop
    if (done) break;

    // Otherwise go back to polling as long as it doesn't exceed max_pollers_
    //
    // **WARNING**:
    // There is a possibility of threads thrashing here (i.e excessive thread
    // shutdowns and creations than the ideal case). This happens if max_poller_
    // count is small and the rate of incoming requests is also small. In such
    // scenarios we can possibly configure max_pollers_ to a higher value and/or
    // increase the cq timeout.
    //
    // However, not doing this check here and unconditionally incrementing
    // num_pollers (and hoping that the system will eventually settle down) has
    // far worse consequences i.e huge number of threads getting created to the
    // point of thread-exhaustion. For example: if the incoming request rate is
    // very high, all the polling threads will return very quickly from
    // PollForWork() with WORK_FOUND. They all briefly decrement num_pollers_
    // counter thereby possibly - and briefly - making it go below min_pollers;
    // This will most likely result in the creation of a new poller since
    // num_pollers_ dipped below min_pollers_.
    //
    // Now, If we didn't do the max_poller_ check here, all these threads will
    // go back to doing PollForWork() and the whole cycle repeats (with a new
    // thread being added in each cycle). Once the total number of threads in
    // the system crosses a certain threshold (around ~1500), there is heavy
    // contention on mutexes (the mu_ here or the mutexes in gRPC core like the
    // pollset mutex) that makes DoWork() take longer to finish thereby causing
    // new poller threads to be created even faster. This results in a thread
    // avalanche.
    if (num_pollers_ < max_pollers_) {
      num_pollers_++;
    } else {
      break;
    }
  };

  // This thread is exiting. Do some cleanup work i.e delete already completed
  // worker threads
  CleanupCompletedThreads();

  // If we are here, either ThreadManager is shutting down or it already has
  // enough threads.
}

}  // namespace grpc
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2014

    @author
    Ryan Pavlik
    <ryan@sensics.com>
    <http://sensics.com>

*/

// Copyright 2014 Sensics, Inc.
//
// All rights reserved.
//
// (Final version intended to be licensed under
// the Apache License, Version 2.0)

// Internal Includes
#include <osvr/Server/Server.h>
#include <osvr/Server/RegisterShutdownHandler.h>

// Library/third-party includes
#include <json/value.h>
#include <json/reader.h>

// Standard includes
#include <iostream>
#include <fstream>
#include <exception>

using std::cout;
using std::cerr;
using std::endl;

static osvr::server::ServerPtr server;

/// @brief Shutdown handler function - forcing the server pointer to be global.
void handleShutdown() {
    cout << "Received shutdown signal..." << endl;
    server->signalStop();
}

int main(int argc, char *argv[]) {
    std::string configName = "osvr_server_config.json";
    if (argc > 2) {
        configName = argv[1];
    }
    cout << "Loading config file '" << configName << "'" << endl;
    Json::Value root;
    Json::Reader reader;
    try {
        std::ifstream config(configName);
        bool parsingSuccessful = reader.parse(config, root);
        if (!parsingSuccessful) {
            cerr << "Error in parsing JSON config file" << endl;
            cerr << reader.getFormattedErrorMessages() << endl;
            return 1;
        }
    } catch (std::exception &e) {
        cerr << "Caught exception loading and parsing JSON config file: "
             << e.what() << endl;
        return 1;
    }

    cout << "Creating server..." << endl;

    server = osvr::server::Server::createLocal();

    cout << "Registering shutdown handler..." << endl;
    osvr::server::registerShutdownHandler<&handleShutdown>();

    cout << "Loading plugins..." << endl;
    const Json::Value plugins = root["plugins"];
    for (Json::ArrayIndex i = 0, e = plugins.size(); i < e; ++i) {
        std::string plugin = plugins[i].asString();
        cout << "Loading plugin '" << plugin << "'..." << endl;
        try {
            server->loadPlugin(plugin);
            cout << "Plugin '" << plugin << "' loaded!\n" << endl;
        } catch (std::exception &e) {
            std::cerr << "Caught exception tring to load " << plugin << ": "
                      << e.what() << std::endl;
            return 1;
        }
    }

    cout << "Instantiating configured drivers..." << endl;
    const Json::Value drivers = root["drivers"];
    for (Json::ArrayIndex i = 0, e = drivers.size(); i < e; ++i) {
        const Json::Value thisDriver = drivers[i];
        cout << "Instantiating '" << thisDriver["driver"].asString()
             << "' from '" << thisDriver["plugin"].asString() << "'..." << endl;
        try {
            server->instantiateDriver(thisDriver["plugin"].asString(),
                                      thisDriver["driver"].asString(),

                                      thisDriver["params"].toStyledString());
            cout << "Instantiation succeeded!\n" << endl;
        } catch (std::exception &e) {
            std::cerr << "Caught exception tring to instantiate: " << e.what()
                      << std::endl;
            return 1;
        }
    }

    cout << "Triggering a hardware detection..." << endl;
    server->triggerHardwareDetect();

    cout << "Starting server mainloop..." << endl;
    server->startAndAwaitShutdown();

    cout << "Server mainloop exited." << endl;

    return 0;
}<commit_msg>Print a little usasge help in the server if you don't pass a param.<commit_after>/** @file
    @brief Implementation

    @date 2014

    @author
    Ryan Pavlik
    <ryan@sensics.com>
    <http://sensics.com>

*/

// Copyright 2014 Sensics, Inc.
//
// All rights reserved.
//
// (Final version intended to be licensed under
// the Apache License, Version 2.0)

// Internal Includes
#include <osvr/Server/Server.h>
#include <osvr/Server/RegisterShutdownHandler.h>

// Library/third-party includes
#include <json/value.h>
#include <json/reader.h>

// Standard includes
#include <iostream>
#include <fstream>
#include <exception>

using std::cout;
using std::cerr;
using std::endl;

static osvr::server::ServerPtr server;

/// @brief Shutdown handler function - forcing the server pointer to be global.
void handleShutdown() {
    cout << "Received shutdown signal..." << endl;
    server->signalStop();
}

int main(int argc, char *argv[]) {
    std::string configName = "osvr_server_config.json";
    if (argc > 2) {
        configName = argv[1];
    } else {
        cout << "Using default config file - pass a filename on the command "
                "line to use a different one." << endl;
    }

    cout << "Loading config file '" << configName << "'" << endl;
    Json::Value root;
    Json::Reader reader;
    try {
        std::ifstream config(configName);
        bool parsingSuccessful = reader.parse(config, root);
        if (!parsingSuccessful) {
            cerr << "Error in parsing JSON config file" << endl;
            cerr << reader.getFormattedErrorMessages() << endl;
            return 1;
        }
    } catch (std::exception &e) {
        cerr << "Caught exception loading and parsing JSON config file: "
             << e.what() << endl;
        return 1;
    }

    cout << "Creating server..." << endl;

    server = osvr::server::Server::createLocal();

    cout << "Registering shutdown handler..." << endl;
    osvr::server::registerShutdownHandler<&handleShutdown>();

    cout << "Loading plugins..." << endl;
    const Json::Value plugins = root["plugins"];
    for (Json::ArrayIndex i = 0, e = plugins.size(); i < e; ++i) {
        std::string plugin = plugins[i].asString();
        cout << "Loading plugin '" << plugin << "'..." << endl;
        try {
            server->loadPlugin(plugin);
            cout << "Plugin '" << plugin << "' loaded!\n" << endl;
        } catch (std::exception &e) {
            std::cerr << "Caught exception tring to load " << plugin << ": "
                      << e.what() << std::endl;
            return 1;
        }
    }

    cout << "Instantiating configured drivers..." << endl;
    const Json::Value drivers = root["drivers"];
    for (Json::ArrayIndex i = 0, e = drivers.size(); i < e; ++i) {
        const Json::Value thisDriver = drivers[i];
        cout << "Instantiating '" << thisDriver["driver"].asString()
             << "' from '" << thisDriver["plugin"].asString() << "'..." << endl;
        try {
            server->instantiateDriver(thisDriver["plugin"].asString(),
                                      thisDriver["driver"].asString(),

                                      thisDriver["params"].toStyledString());
            cout << "Instantiation succeeded!\n" << endl;
        } catch (std::exception &e) {
            std::cerr << "Caught exception tring to instantiate: " << e.what()
                      << std::endl;
            return 1;
        }
    }

    cout << "Triggering a hardware detection..." << endl;
    server->triggerHardwareDetect();

    cout << "Starting server mainloop..." << endl;
    server->startAndAwaitShutdown();

    cout << "Server mainloop exited." << endl;

    return 0;
}<|endoftext|>


<commit_before>/***************************************************************************
*   Copyright (C) 2004 by Jason Kivlighn                                  *
*   (jkivlighn@gmail.com)                                                 *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
***************************************************************************/

#include "refineshoppinglistdialog.h"

#include <qvariant.h>
#include <qpushbutton.h>
#include <qlabel.h>
#include <q3header.h>
#include <qlayout.h>
#include <qtooltip.h>
#include <q3whatsthis.h>
//Added by qt3to4:
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <KVBox>
#include <klocale.h>
#include <kapplication.h>
#include <kcursor.h>
#include <kconfig.h>
#include <kglobal.h>

#include "backends/recipedb.h"
#include "widgets/krelistview.h"
#include "widgets/ingredientlistview.h"
#include "shoppinglistviewdialog.h"
#include "shoppingcalculator.h"
#include "datablocks/mixednumber.h"

RefineShoppingListDialog::RefineShoppingListDialog( QWidget* parent, RecipeDB *db, const ElementList &recipeList )
		: KDialog( parent),
		database( db )
{
    setButtons(KDialog::Ok);
    setDefaultButton(KDialog::Ok);
    setModal( true );

    KVBox *page = new KVBox( this );
    setMainWidget( page );

	setButtonText( KDialog::Ok, i18n( "&Done" ) );

	helpLabel = new QLabel( page );
   helpLabel->setObjectName( "helpLabel" );
	helpLabel->setTextFormat( Qt::RichText );
        helpLabel->setWordWrap(true);
	QWidget *layout2Widget = new QWidget(page);

	QHBoxLayout *layout2 = new QHBoxLayout( layout2Widget );
   layout2->setObjectName( "layout2" );
   layout2->setMargin( 0 );
   layout2->setSpacing( 6 );

	allIngListView = new KreListView( layout2Widget, QString::null, true, 0 );
	StdIngredientListView *list_view = new StdIngredientListView(allIngListView,database);
	list_view->reload();
 	allIngListView->setListView(list_view);
	layout2->addWidget( allIngListView );

	layout1 = new QVBoxLayout( );
   layout1->setObjectName( "layout1" );
   layout1->setMargin( 0 );
   layout1->setSpacing( 6 );

	addButton = new QPushButton( layout2Widget );
   addButton->setObjectName( "addButton" );
	addButton->setIcon( KIcon( "go-next" ) );
	addButton->setFixedSize( QSize( 32, 32 ) );
	layout1->addWidget( addButton );

	removeButton = new QPushButton( layout2Widget );
   removeButton->setObjectName( "removeButton" );
	removeButton->setIcon( KIcon( "go-previous" ) );
	removeButton->setFixedSize( QSize( 32, 32 ) );
	layout1->addWidget( removeButton );
	spacer1 = new QSpacerItem( 51, 191, QSizePolicy::Minimum, QSizePolicy::Expanding );
	layout1->addItem( spacer1 );
	layout2->addLayout( layout1 );

	ingListView = new KreListView( layout2Widget, QString::null, true );
	ingListView->listView() ->addColumn( i18n( "Ingredients in Shopping List" ) );
	ingListView->listView() ->addColumn( i18n( "Amount" ) );
	ingListView->listView() ->addColumn( i18n( "Unit" ) );
	ingListView->listView() ->setItemsRenameable( true );
	ingListView->listView() ->setRenameable( 0, false );
	ingListView->listView() ->setRenameable( 1, true );
	ingListView->listView() ->setRenameable( 2, true );
	layout2->addWidget( ingListView );

	languageChange();

	//clearWState( WState_Polished );

	connect( addButton, SIGNAL( clicked() ), this, SLOT( addIngredient() ) );
	connect( removeButton, SIGNAL( clicked() ), this, SLOT( removeIngredient() ) );
	connect( ingListView->listView(), SIGNAL( itemRenamed( Q3ListViewItem*, const QString &, int ) ), SLOT( itemRenamed( Q3ListViewItem*, const QString &, int ) ) );

	KApplication::setOverrideCursor( Qt::WaitCursor );
	calculateShopping( recipeList, &ingredientList, database );
	KApplication::restoreOverrideCursor();

	loadData();
}

RefineShoppingListDialog::~RefineShoppingListDialog()
{}

void RefineShoppingListDialog::languageChange()
{
	helpLabel->setText( i18n( "On the right are the ingredients needed for the recipes you selected.  You may now add additional ingredients, remove ingredients you do not need, or modify the amounts of existing ingredients." ) );
	allIngListView->listView() ->header() ->setLabel( 0, i18n( "Ingredients" ) );
	ingListView->listView() ->header() ->setLabel( 0, i18n( "Ingredients in Shopping List" ) );
	ingListView->listView() ->header() ->setLabel( 1, i18n( "Amount" ) );
	ingListView->listView() ->header() ->setLabel( 2, i18n( "Unit" ) );
}

void RefineShoppingListDialog::accept()
{
	hide();

	ShoppingListViewDialog view( this, ingredientList );
	view.exec();

	QDialog::accept();
}

void RefineShoppingListDialog::loadData()
{
	for ( IngredientList::iterator it = ingredientList.begin(); it != ingredientList.end(); ++it ) {
		//from here on, the shopping list will work with the upper value of the range (if exists)
		(*it).amount = (*it).amount+(*it).amount_offset;
		(*it).amount_offset = 0;

		QString amount_str;
		if ( ( *it ).amount > 0 ) {
                    KConfigGroup config( KGlobal::config(), "Formatting" );

			if ( !config.readEntry( "Fraction" ).isEmpty() )
				amount_str = MixedNumber( ( *it ).amount ).toString();
			else
				amount_str = beautify( KGlobal::locale() ->formatNumber( ( *it ).amount, 5 ) );
		}

		Q3ListViewItem *new_item = new Q3ListViewItem( ingListView->listView(), ( *it ).name, amount_str, ( *it ).amount > 1 ? ( *it ).units.plural : ( *it ).units.name );
		item_ing_map.insert( new_item, it );
	}
}

void RefineShoppingListDialog::addIngredient()
{
	Q3ListViewItem * item = allIngListView->listView() ->selectedItem();
	if ( item ) {
		Q3ListViewItem * new_item = new Q3ListViewItem( ingListView->listView(), item->text( 0 ) );
		ingListView->listView() ->setSelected( new_item, true );
		ingListView->listView() ->ensureItemVisible( new_item );
		allIngListView->listView() ->setSelected( item, false );

		item_ing_map.insert( new_item, ingredientList.append( Ingredient( item->text( 0 ), 0, Unit() ) ) );
	}
}

void RefineShoppingListDialog::removeIngredient()
{
	Q3ListViewItem * item = ingListView->listView() ->selectedItem();
	if ( item ) {
		for ( IngredientList::iterator it = ingredientList.begin(); it != ingredientList.end(); ++it ) {
			if ( *item_ing_map.find( item ) == it ) {
				ingredientList.remove( it );
				item_ing_map.remove( item );
				break;
			}
		}
		delete item;
	}
}

void RefineShoppingListDialog::itemRenamed( Q3ListViewItem* item, const QString &new_text, int col )
{
	if ( col == 1 ) {
		IngredientList::iterator found_it = *item_ing_map.find( item );

		bool ok;
		MixedNumber amount = MixedNumber::fromString( new_text, &ok );
		if ( ok ) {
			( *found_it ).amount = amount.toDouble();
		}
		else { //revert back to the valid amount string
			QString amount_str;
			if ( ( *found_it ).amount > 0 ) {
                            KConfigGroup config( KGlobal::config(), "Formatting" );

				if ( !config.readEntry( "Fraction" ).isEmpty() )
					amount_str = MixedNumber( ( *found_it ).amount ).toString();
				else
					amount_str = beautify( KGlobal::locale() ->formatNumber( ( *found_it ).amount, 5 ) );
			}

			item->setText( 1, amount_str );
		}
	}
	else if ( col == 2 ) {
		IngredientList::iterator found_it = *item_ing_map.find( item );

		if ( ( *found_it ).amount > 1 )
			( *found_it ).units.plural = new_text;
		else
			( *found_it ).units.name = new_text;
	}
}

#include "refineshoppinglistdialog.moc"
<commit_msg>Removed unnecesary includes.<commit_after>/***************************************************************************
*   Copyright (C) 2004 by Jason Kivlighn                                  *
*   (jkivlighn@gmail.com)                                                 *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
***************************************************************************/

#include "refineshoppinglistdialog.h"

#include <qvariant.h>
#include <qpushbutton.h>
#include <qlabel.h>
#include <q3header.h>
#include <qlayout.h>
//Added by qt3to4:
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <KVBox>
#include <klocale.h>
#include <kapplication.h>
#include <kcursor.h>
#include <kconfig.h>
#include <kglobal.h>

#include "backends/recipedb.h"
#include "widgets/krelistview.h"
#include "widgets/ingredientlistview.h"
#include "shoppinglistviewdialog.h"
#include "shoppingcalculator.h"
#include "datablocks/mixednumber.h"

RefineShoppingListDialog::RefineShoppingListDialog( QWidget* parent, RecipeDB *db, const ElementList &recipeList )
		: KDialog( parent),
		database( db )
{
    setButtons(KDialog::Ok);
    setDefaultButton(KDialog::Ok);
    setModal( true );

    KVBox *page = new KVBox( this );
    setMainWidget( page );

	setButtonText( KDialog::Ok, i18n( "&Done" ) );

	helpLabel = new QLabel( page );
   helpLabel->setObjectName( "helpLabel" );
	helpLabel->setTextFormat( Qt::RichText );
        helpLabel->setWordWrap(true);
	QWidget *layout2Widget = new QWidget(page);

	QHBoxLayout *layout2 = new QHBoxLayout( layout2Widget );
   layout2->setObjectName( "layout2" );
   layout2->setMargin( 0 );
   layout2->setSpacing( 6 );

	allIngListView = new KreListView( layout2Widget, QString::null, true, 0 );
	StdIngredientListView *list_view = new StdIngredientListView(allIngListView,database);
	list_view->reload();
 	allIngListView->setListView(list_view);
	layout2->addWidget( allIngListView );

	layout1 = new QVBoxLayout( );
   layout1->setObjectName( "layout1" );
   layout1->setMargin( 0 );
   layout1->setSpacing( 6 );

	addButton = new QPushButton( layout2Widget );
   addButton->setObjectName( "addButton" );
	addButton->setIcon( KIcon( "go-next" ) );
	addButton->setFixedSize( QSize( 32, 32 ) );
	layout1->addWidget( addButton );

	removeButton = new QPushButton( layout2Widget );
   removeButton->setObjectName( "removeButton" );
	removeButton->setIcon( KIcon( "go-previous" ) );
	removeButton->setFixedSize( QSize( 32, 32 ) );
	layout1->addWidget( removeButton );
	spacer1 = new QSpacerItem( 51, 191, QSizePolicy::Minimum, QSizePolicy::Expanding );
	layout1->addItem( spacer1 );
	layout2->addLayout( layout1 );

	ingListView = new KreListView( layout2Widget, QString::null, true );
	ingListView->listView() ->addColumn( i18n( "Ingredients in Shopping List" ) );
	ingListView->listView() ->addColumn( i18n( "Amount" ) );
	ingListView->listView() ->addColumn( i18n( "Unit" ) );
	ingListView->listView() ->setItemsRenameable( true );
	ingListView->listView() ->setRenameable( 0, false );
	ingListView->listView() ->setRenameable( 1, true );
	ingListView->listView() ->setRenameable( 2, true );
	layout2->addWidget( ingListView );

	languageChange();

	//clearWState( WState_Polished );

	connect( addButton, SIGNAL( clicked() ), this, SLOT( addIngredient() ) );
	connect( removeButton, SIGNAL( clicked() ), this, SLOT( removeIngredient() ) );
	connect( ingListView->listView(), SIGNAL( itemRenamed( Q3ListViewItem*, const QString &, int ) ), SLOT( itemRenamed( Q3ListViewItem*, const QString &, int ) ) );

	KApplication::setOverrideCursor( Qt::WaitCursor );
	calculateShopping( recipeList, &ingredientList, database );
	KApplication::restoreOverrideCursor();

	loadData();
}

RefineShoppingListDialog::~RefineShoppingListDialog()
{}

void RefineShoppingListDialog::languageChange()
{
	helpLabel->setText( i18n( "On the right are the ingredients needed for the recipes you selected.  You may now add additional ingredients, remove ingredients you do not need, or modify the amounts of existing ingredients." ) );
	allIngListView->listView() ->header() ->setLabel( 0, i18n( "Ingredients" ) );
	ingListView->listView() ->header() ->setLabel( 0, i18n( "Ingredients in Shopping List" ) );
	ingListView->listView() ->header() ->setLabel( 1, i18n( "Amount" ) );
	ingListView->listView() ->header() ->setLabel( 2, i18n( "Unit" ) );
}

void RefineShoppingListDialog::accept()
{
	hide();

	ShoppingListViewDialog view( this, ingredientList );
	view.exec();

	QDialog::accept();
}

void RefineShoppingListDialog::loadData()
{
	for ( IngredientList::iterator it = ingredientList.begin(); it != ingredientList.end(); ++it ) {
		//from here on, the shopping list will work with the upper value of the range (if exists)
		(*it).amount = (*it).amount+(*it).amount_offset;
		(*it).amount_offset = 0;

		QString amount_str;
		if ( ( *it ).amount > 0 ) {
                    KConfigGroup config( KGlobal::config(), "Formatting" );

			if ( !config.readEntry( "Fraction" ).isEmpty() )
				amount_str = MixedNumber( ( *it ).amount ).toString();
			else
				amount_str = beautify( KGlobal::locale() ->formatNumber( ( *it ).amount, 5 ) );
		}

		Q3ListViewItem *new_item = new Q3ListViewItem( ingListView->listView(), ( *it ).name, amount_str, ( *it ).amount > 1 ? ( *it ).units.plural : ( *it ).units.name );
		item_ing_map.insert( new_item, it );
	}
}

void RefineShoppingListDialog::addIngredient()
{
	Q3ListViewItem * item = allIngListView->listView() ->selectedItem();
	if ( item ) {
		Q3ListViewItem * new_item = new Q3ListViewItem( ingListView->listView(), item->text( 0 ) );
		ingListView->listView() ->setSelected( new_item, true );
		ingListView->listView() ->ensureItemVisible( new_item );
		allIngListView->listView() ->setSelected( item, false );

		item_ing_map.insert( new_item, ingredientList.append( Ingredient( item->text( 0 ), 0, Unit() ) ) );
	}
}

void RefineShoppingListDialog::removeIngredient()
{
	Q3ListViewItem * item = ingListView->listView() ->selectedItem();
	if ( item ) {
		for ( IngredientList::iterator it = ingredientList.begin(); it != ingredientList.end(); ++it ) {
			if ( *item_ing_map.find( item ) == it ) {
				ingredientList.remove( it );
				item_ing_map.remove( item );
				break;
			}
		}
		delete item;
	}
}

void RefineShoppingListDialog::itemRenamed( Q3ListViewItem* item, const QString &new_text, int col )
{
	if ( col == 1 ) {
		IngredientList::iterator found_it = *item_ing_map.find( item );

		bool ok;
		MixedNumber amount = MixedNumber::fromString( new_text, &ok );
		if ( ok ) {
			( *found_it ).amount = amount.toDouble();
		}
		else { //revert back to the valid amount string
			QString amount_str;
			if ( ( *found_it ).amount > 0 ) {
                            KConfigGroup config( KGlobal::config(), "Formatting" );

				if ( !config.readEntry( "Fraction" ).isEmpty() )
					amount_str = MixedNumber( ( *found_it ).amount ).toString();
				else
					amount_str = beautify( KGlobal::locale() ->formatNumber( ( *found_it ).amount, 5 ) );
			}

			item->setText( 1, amount_str );
		}
	}
	else if ( col == 2 ) {
		IngredientList::iterator found_it = *item_ing_map.find( item );

		if ( ( *found_it ).amount > 1 )
			( *found_it ).units.plural = new_text;
		else
			( *found_it ).units.name = new_text;
	}
}

#include "refineshoppinglistdialog.moc"
<|endoftext|>


<commit_before>/*
 *   Copyright (C) 2014 Pelagicore AB
 *   All rights reserved.
 */
#include "debug.h"
#include "generators.h"
#include "jansson.h"

#include "devicenodegateway.h"

DeviceNodeGateway::DeviceNodeGateway(ControllerAbstractInterface *controllerInterface):
    Gateway(controllerInterface),
    m_controllerIface(controllerInterface)
{
}

std::string DeviceNodeGateway::id()
{
    return "devicenode";
}

std::string DeviceNodeGateway::environment()
{
    return "";
}

bool DeviceNodeGateway::setConfig(const std::string &config)
{
    json_error_t  error;
    json_t       *root = NULL, *devices = NULL;
    bool success = true;
    std::vector<struct Device> newDevList;

    log_debug("DeviceNodeGateway::setConfig called\n");

    /* Get root JSON object */
    root = json_loads(config.c_str(), 0, &error);

    if (!root) {
        log_error("Error on line %d: %s\n", error.line, error.text);
        success = false;
        goto cleanup_setConfig;
    }

    // Get string
    devices = json_object_get(root, "devices");

    if (!json_is_array(devices)) {
        log_error("Value is not an array.");
        log_error("error: on line %d: %s\n", error.line, error.text);
        success = false;
        goto cleanup_setConfig;
    }

    newDevList = parseDeviceList(devices, success);
    if (success) {
        m_devList = newDevList;
    }

cleanup_setConfig:

    // Also frees 'devices'
    if (root)
        json_decref (root);

    return success;
}

std::vector<struct DeviceNodeGateway::Device>
DeviceNodeGateway::parseDeviceList(json_t *list, bool &ok) {
    ok = true;
    std::vector<struct DeviceNodeGateway::Device> dev_list;
    for (uint i = 0; i < json_array_size(list); i++) {
        struct DeviceNodeGateway::Device dev;
        json_t *device = 0;
        std::string* fields[] = {&dev.name, &dev.major, &dev.minor, &dev.mode};
        std::string  fieldsStr[] = {"name", "major", "minor", "mode"};
        uint numFields = 4;

        device = json_array_get(list, i);
        if (ok && !json_is_object(device)) {
            log_error ("Expected JSON device object, found something else");
            ok = false;
        }

        for (uint j = 0; ok && j < numFields; j++) {
            json_t *value = 0;
            value = json_object_get (device, fieldsStr[j].c_str());
            if (ok && !json_is_string(value)) {
                log_error (std::string("Key '" + fieldsStr[j] +
                           "' is not a member of device object!").c_str());
                ok = false;
            }
            if (json_string_value(value)) {
                *fields[j] = std::string(json_string_value(value));
                ok = true;
            } else {
                ok = false;
                break;
            }
        }

        if (ok) {
            dev_list.push_back(dev);
        } else {
            break;
        }
    }
    return dev_list;
}

bool DeviceNodeGateway::activate()
{
    bool success = true;

    for (uint i = 0; i < m_devList.size(); i++)
    {
        struct DeviceNodeGateway::Device dev;
        dev = m_devList.at(i);
        success &= m_controllerIface->systemCall("mknod " + dev.name + " c " +
                                       dev.major + " " + dev.minor);
        if (success) {
            success &= m_controllerIface->systemCall("chmod " +
            dev.mode + " " + dev.name );
        } else {
            log_debug (std::string("Failed to create device " + dev.name)
                            .c_str());
        }
    }

    return success;
}
<commit_msg>Simplified logic in DeviceNodeGateway::parseDeviceList<commit_after>/*
 *   Copyright (C) 2014 Pelagicore AB
 *   All rights reserved.
 */
#include "debug.h"
#include "generators.h"
#include "jansson.h"

#include "devicenodegateway.h"

DeviceNodeGateway::DeviceNodeGateway(ControllerAbstractInterface *controllerInterface):
    Gateway(controllerInterface),
    m_controllerIface(controllerInterface)
{
}

std::string DeviceNodeGateway::id()
{
    return "devicenode";
}

std::string DeviceNodeGateway::environment()
{
    return "";
}

bool DeviceNodeGateway::setConfig(const std::string &config)
{
    json_error_t  error;
    json_t       *root = NULL, *devices = NULL;
    bool success = true;
    std::vector<struct Device> newDevList;

    log_debug("DeviceNodeGateway::setConfig called\n");

    /* Get root JSON object */
    root = json_loads(config.c_str(), 0, &error);

    if (!root) {
        log_error("Error on line %d: %s\n", error.line, error.text);
        success = false;
        goto cleanup_setConfig;
    }

    // Get string
    devices = json_object_get(root, "devices");

    if (!json_is_array(devices)) {
        log_error("Value is not an array.");
        log_error("error: on line %d: %s\n", error.line, error.text);
        success = false;
        goto cleanup_setConfig;
    }

    newDevList = parseDeviceList(devices, success);
    if (success) {
        m_devList = newDevList;
    }

cleanup_setConfig:

    // Also frees 'devices'
    if (root)
        json_decref (root);

    return success;
}

std::vector<struct DeviceNodeGateway::Device>
DeviceNodeGateway::parseDeviceList(json_t *list, bool &ok) {
    ok = true;
    std::vector<struct DeviceNodeGateway::Device> dev_list;
    for (uint i = 0; i < json_array_size(list); i++) {
        struct DeviceNodeGateway::Device dev;
        json_t *device = 0;
        std::string* fields[] = {&dev.name, &dev.major, &dev.minor, &dev.mode};
        std::string  fieldsStr[] = {"name", "major", "minor", "mode"};
        uint numFields = 4;

        device = json_array_get(list, i);
        if (ok && !json_is_object(device)) {
            log_error ("Expected JSON device object, found something else");
            ok = false;
        }

        for (uint j = 0; ok && j < numFields; j++) {
            json_t *value = 0;
            value = json_object_get (device, fieldsStr[j].c_str());
            if (ok && !json_is_string(value)) {
                log_error (std::string("Key '" + fieldsStr[j] +
                           "' is not a member of device object!").c_str());
                ok = false;
            }
            if (json_string_value(value)) {
                *fields[j] = std::string(json_string_value(value));
                ok = true;
            } else {
                ok = false;
                break;
            }
        }

        if (ok) {
            dev_list.push_back(dev);
        } else {
            break;
        }
    }
    return dev_list;
}

bool DeviceNodeGateway::activate()
{
    bool success = true;
    for (uint i = 0; i < m_devList.size(); i++)
    {
        struct DeviceNodeGateway::Device dev;
        dev = m_devList.at(i);
        success = m_controllerIface->systemCall("mknod " + dev.name + " c " +
                                       dev.major + " " + dev.minor);
        if (success) {
            success = m_controllerIface->systemCall("chmod " +
            dev.mode + " " + dev.name );
        } else {
            log_debug (std::string("Failed to create device " + dev.name)
                            .c_str());
        }
    }

    return success;
}
<|endoftext|>