<commit_before>
//@HEADER
// ************************************************************************
//
//               HPCG: Simple Conjugate Gradient Benchmark Code
// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
//
// ************************************************************************
//@HEADER

/*!
 @file CG.cpp

 HPCG routine
 */

#ifdef HPCG_DETAILED_DEBUG
#include <fstream>
using std::endl;
#include "hpcg.hpp"
#include <cassert>
#endif

#include "SetupHalo.hpp"
#include "mytimer.hpp"

#ifndef HPCG_NOMPI
#include <mpi.h>
#include <map>
#include <set>
#endif

#ifndef HPCG_NOOPENMP
#include <omp.h>
#endif

/*!
  Prepares system matrix data structure and creates data necessary necessary
  for communication of boundary values of this process.

  @param[in]    geom The description of the problem's geometry.
  @param[inout] A    The known system matrix

  @see ExchangeHalo
*/
void SetupHalo(const Geometry & geom, SparseMatrix & A) {

	// Extract Matrix pieces

	local_int_t localNumberOfRows = A.localNumberOfRows;
	char  * nonzerosInRow = A.nonzerosInRow;
	global_int_t ** mtxIndG = A.mtxIndG;
	local_int_t ** mtxIndL = A.mtxIndL;

#ifdef HPCG_NOMPI  // In the non-MPI case we simply copy global indices to local index storage
#ifndef HPCG_NOOPENMP
#pragma omp parallel for
#endif
	for (local_int_t i=0; i< localNumberOfRows; i++) {
		int cur_nnz = nonzerosInRow[i];
		for (int j=0; j<cur_nnz; j++)	mtxIndL[i][j] = mtxIndG[i][j];
	}

#else // Run this section if compiling for MPI

	// Scan global IDs of the nonzeros in the matrix.  Determine if the column ID matches a row ID.  If not:
	// 1) We call the getRankOfMatrixRow function, which tells us the rank of the processor owning the row ID.
	//	We need to receive this value of the x vector during the halo exchange.
	// 2) We record our row ID since we know that the other processor will need this value from us, due to symmetry.

	std::map< int, std::set< global_int_t> > sendList, receiveList;
	typedef std::map< int, std::set< global_int_t> >::iterator map_iter;
	typedef std::set<global_int_t>::iterator set_iter;
	std::map< local_int_t, local_int_t > externalToLocalMap;

	// TODO: With proper critical and atomic regions, this loop could be threaded, but not attempting it at this time
	for (local_int_t i=0; i< localNumberOfRows; i++) {
		global_int_t currentGlobalRow = A.localToGlobalMap[i];
		for (int j=0; j<nonzerosInRow[i]; j++) {
			global_int_t curIndex = mtxIndG[i][j];
			int rankIdOfColumnEntry = getRankOfMatrixRow(geom, curIndex);
#ifdef HPCG_DETAILED_DEBUG
			HPCG_fout << "rank, row , col, globalToLocalMap[col] = " << geom.rank << " " << currentGlobalRow << " "
					<< curIndex << " " << A.globalToLocalMap[curIndex] << endl;
#endif
			if (geom.rank!=rankIdOfColumnEntry) {// If column index is not a row index, then it comes from another processor
				receiveList[rankIdOfColumnEntry].insert(curIndex);
				sendList[rankIdOfColumnEntry].insert(currentGlobalRow); // Matrix symmetry means we know the neighbor process wants my value
			}
		}
	}

	// Count number of matrix entries to send and receive
	local_int_t totalToBeSent = 0;
	for (map_iter curNeighbor = sendList.begin(); curNeighbor != sendList.end(); ++curNeighbor) {
		totalToBeSent += (curNeighbor->second).size();
	}
	local_int_t totalToBeReceived = 0;
	for (map_iter curNeighbor = receiveList.begin(); curNeighbor != receiveList.end(); ++curNeighbor) {
		totalToBeReceived += (curNeighbor->second).size();
	}

#ifdef HPCG_DETAILED_DEBUG
	// These are all attributes that should be true, due to symmetry
	HPCG_fout << "totalToBeSent = " << totalToBeSent << " totalToBeReceived = " << totalToBeReceived << endl;
	assert(totalToBeSent==totalToBeReceived); // Number of sent entry should equal number of received
	assert(sendList.size()==receiveList.size()); // Number of send-to neighbors should equal number of receive-from
	// Each receive-from neighbor should be a send-to neighbor, and send the same number of entries
	for (map_iter curNeighbor = receiveList.begin(); curNeighbor != receiveList.end(); ++curNeighbor) {
		assert(sendList.find(curNeighbor->first)!=sendList.end());
		assert(sendList[curNeighbor->first].size()==receiveList[curNeighbor->first].size());
	}
#endif

	// Build the arrays and lists needed by the ExchangeHalo function.
	double * sendBuffer = new double[totalToBeSent];
	local_int_t * elementsToSend = new local_int_t[totalToBeSent];
	int * neighbors = new int[sendList.size()];
	local_int_t * receiveLength = new local_int_t[receiveList.size()];
	local_int_t * sendLength = new local_int_t[sendList.size()];
	int neighborCount = 0;
	local_int_t receiveEntryCount = 0;
	local_int_t sendEntryCount = 0;
	for (map_iter curNeighbor = receiveList.begin(); curNeighbor != receiveList.end(); ++curNeighbor, ++neighborCount) {
		int neighborId = curNeighbor->first; // rank of current neighbor we are processing
		neighbors[neighborCount] = neighborId; // store rank ID of current neighbor
		receiveLength[neighborCount] = receiveList[neighborId].size();
		sendLength[neighborCount] = sendList[neighborId].size(); // Get count if sends/receives
		for (set_iter i = receiveList[neighborId].begin(); i != receiveList[neighborId].end(); ++i, ++receiveEntryCount) {
			externalToLocalMap[*i] = localNumberOfRows + receiveEntryCount; // The remote columns are indexed at end of internals
		}
		for (set_iter i = sendList[neighborId].begin(); i != sendList[neighborId].end(); ++i, ++sendEntryCount) {
			//if (geom.rank==1) HPCG_fout << "*i, globalToLocalMap[*i], sendEntryCount = " << *i << " " << A.globalToLocalMap[*i] << " " << sendEntryCount << endl;
			elementsToSend[sendEntryCount] = A.globalToLocalMap[*i]; // store local ids of entry to send
		}
	}

	// Convert matrix indices to local IDs
#ifndef HPCG_NOOPENMP
#pragma omp parallel for
#endif
	for (local_int_t i=0; i< localNumberOfRows; i++) {
		for (int j=0; j<nonzerosInRow[i]; j++) {
			global_int_t curIndex = mtxIndG[i][j];
			int rankIdOfColumnEntry = getRankOfMatrixRow(geom, curIndex);
			if (geom.rank==rankIdOfColumnEntry) { // My column index, so convert to local index
				mtxIndL[i][j] = A.globalToLocalMap[curIndex];
			}
			else { // If column index is not a row index, then it comes from another processor
				mtxIndL[i][j] = externalToLocalMap[curIndex];
			}
		}
	}

	// Store contents in our matrix struct
	A.numberOfExternalValues = externalToLocalMap.size();
	A.localNumberOfColumns = A.localNumberOfRows + A.numberOfExternalValues;
	A.numberOfSendNeighbors = sendList.size();
	A.totalToBeSent = totalToBeSent;
	A.elementsToSend = elementsToSend;
	A.neighbors = neighbors;
	A.receiveLength = receiveLength;
	A.sendLength = sendLength;
	A.sendBuffer = sendBuffer;

#ifdef HPCG_DETAILED_DEBUG
	HPCG_fout << " For rank " << geom.rank << " of " << geom.size << ", number of neighbors = " << A.numberOfSendNeighbors << endl;
	for (int i = 0; i < A.numberOfSendNeighbors; i++) {
		HPCG_fout << "     rank " << geom.rank << " neighbor " << neighbors[i] << " send/recv length = " << sendLength[i] << "/" << receiveLength[i] << endl;
		for (local_int_t j = 0; j<sendLength[i]; ++j)
			HPCG_fout << "       rank " << geom.rank << " elementsToSend[" << j << "] = " << elementsToSend[j] << endl;
	}
#endif

#endif // ifndef HPCG_NOMPI

	return;
}
<commit_msg>Wrong file name in comment.<commit_after>
//@HEADER
// ************************************************************************
//
//               HPCG: Simple Conjugate Gradient Benchmark Code
// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
//
// ************************************************************************
//@HEADER

/*!
 @file SetupHalo.cpp

 HPCG routine
 */

#ifdef HPCG_DETAILED_DEBUG
#include <fstream>
using std::endl;
#include "hpcg.hpp"
#include <cassert>
#endif

#include "SetupHalo.hpp"
#include "mytimer.hpp"

#ifndef HPCG_NOMPI
#include <mpi.h>
#include <map>
#include <set>
#endif

#ifndef HPCG_NOOPENMP
#include <omp.h>
#endif

/*!
  Prepares system matrix data structure and creates data necessary necessary
  for communication of boundary values of this process.

  @param[in]    geom The description of the problem's geometry.
  @param[inout] A    The known system matrix

  @see ExchangeHalo
*/
void SetupHalo(const Geometry & geom, SparseMatrix & A) {

	// Extract Matrix pieces

	local_int_t localNumberOfRows = A.localNumberOfRows;
	char  * nonzerosInRow = A.nonzerosInRow;
	global_int_t ** mtxIndG = A.mtxIndG;
	local_int_t ** mtxIndL = A.mtxIndL;

#ifdef HPCG_NOMPI  // In the non-MPI case we simply copy global indices to local index storage
#ifndef HPCG_NOOPENMP
#pragma omp parallel for
#endif
	for (local_int_t i=0; i< localNumberOfRows; i++) {
		int cur_nnz = nonzerosInRow[i];
		for (int j=0; j<cur_nnz; j++)	mtxIndL[i][j] = mtxIndG[i][j];
	}

#else // Run this section if compiling for MPI

	// Scan global IDs of the nonzeros in the matrix.  Determine if the column ID matches a row ID.  If not:
	// 1) We call the getRankOfMatrixRow function, which tells us the rank of the processor owning the row ID.
	//	We need to receive this value of the x vector during the halo exchange.
	// 2) We record our row ID since we know that the other processor will need this value from us, due to symmetry.

	std::map< int, std::set< global_int_t> > sendList, receiveList;
	typedef std::map< int, std::set< global_int_t> >::iterator map_iter;
	typedef std::set<global_int_t>::iterator set_iter;
	std::map< local_int_t, local_int_t > externalToLocalMap;

	// TODO: With proper critical and atomic regions, this loop could be threaded, but not attempting it at this time
	for (local_int_t i=0; i< localNumberOfRows; i++) {
		global_int_t currentGlobalRow = A.localToGlobalMap[i];
		for (int j=0; j<nonzerosInRow[i]; j++) {
			global_int_t curIndex = mtxIndG[i][j];
			int rankIdOfColumnEntry = getRankOfMatrixRow(geom, curIndex);
#ifdef HPCG_DETAILED_DEBUG
			HPCG_fout << "rank, row , col, globalToLocalMap[col] = " << geom.rank << " " << currentGlobalRow << " "
					<< curIndex << " " << A.globalToLocalMap[curIndex] << endl;
#endif
			if (geom.rank!=rankIdOfColumnEntry) {// If column index is not a row index, then it comes from another processor
				receiveList[rankIdOfColumnEntry].insert(curIndex);
				sendList[rankIdOfColumnEntry].insert(currentGlobalRow); // Matrix symmetry means we know the neighbor process wants my value
			}
		}
	}

	// Count number of matrix entries to send and receive
	local_int_t totalToBeSent = 0;
	for (map_iter curNeighbor = sendList.begin(); curNeighbor != sendList.end(); ++curNeighbor) {
		totalToBeSent += (curNeighbor->second).size();
	}
	local_int_t totalToBeReceived = 0;
	for (map_iter curNeighbor = receiveList.begin(); curNeighbor != receiveList.end(); ++curNeighbor) {
		totalToBeReceived += (curNeighbor->second).size();
	}

#ifdef HPCG_DETAILED_DEBUG
	// These are all attributes that should be true, due to symmetry
	HPCG_fout << "totalToBeSent = " << totalToBeSent << " totalToBeReceived = " << totalToBeReceived << endl;
	assert(totalToBeSent==totalToBeReceived); // Number of sent entry should equal number of received
	assert(sendList.size()==receiveList.size()); // Number of send-to neighbors should equal number of receive-from
	// Each receive-from neighbor should be a send-to neighbor, and send the same number of entries
	for (map_iter curNeighbor = receiveList.begin(); curNeighbor != receiveList.end(); ++curNeighbor) {
		assert(sendList.find(curNeighbor->first)!=sendList.end());
		assert(sendList[curNeighbor->first].size()==receiveList[curNeighbor->first].size());
	}
#endif

	// Build the arrays and lists needed by the ExchangeHalo function.
	double * sendBuffer = new double[totalToBeSent];
	local_int_t * elementsToSend = new local_int_t[totalToBeSent];
	int * neighbors = new int[sendList.size()];
	local_int_t * receiveLength = new local_int_t[receiveList.size()];
	local_int_t * sendLength = new local_int_t[sendList.size()];
	int neighborCount = 0;
	local_int_t receiveEntryCount = 0;
	local_int_t sendEntryCount = 0;
	for (map_iter curNeighbor = receiveList.begin(); curNeighbor != receiveList.end(); ++curNeighbor, ++neighborCount) {
		int neighborId = curNeighbor->first; // rank of current neighbor we are processing
		neighbors[neighborCount] = neighborId; // store rank ID of current neighbor
		receiveLength[neighborCount] = receiveList[neighborId].size();
		sendLength[neighborCount] = sendList[neighborId].size(); // Get count if sends/receives
		for (set_iter i = receiveList[neighborId].begin(); i != receiveList[neighborId].end(); ++i, ++receiveEntryCount) {
			externalToLocalMap[*i] = localNumberOfRows + receiveEntryCount; // The remote columns are indexed at end of internals
		}
		for (set_iter i = sendList[neighborId].begin(); i != sendList[neighborId].end(); ++i, ++sendEntryCount) {
			//if (geom.rank==1) HPCG_fout << "*i, globalToLocalMap[*i], sendEntryCount = " << *i << " " << A.globalToLocalMap[*i] << " " << sendEntryCount << endl;
			elementsToSend[sendEntryCount] = A.globalToLocalMap[*i]; // store local ids of entry to send
		}
	}

	// Convert matrix indices to local IDs
#ifndef HPCG_NOOPENMP
#pragma omp parallel for
#endif
	for (local_int_t i=0; i< localNumberOfRows; i++) {
		for (int j=0; j<nonzerosInRow[i]; j++) {
			global_int_t curIndex = mtxIndG[i][j];
			int rankIdOfColumnEntry = getRankOfMatrixRow(geom, curIndex);
			if (geom.rank==rankIdOfColumnEntry) { // My column index, so convert to local index
				mtxIndL[i][j] = A.globalToLocalMap[curIndex];
			}
			else { // If column index is not a row index, then it comes from another processor
				mtxIndL[i][j] = externalToLocalMap[curIndex];
			}
		}
	}

	// Store contents in our matrix struct
	A.numberOfExternalValues = externalToLocalMap.size();
	A.localNumberOfColumns = A.localNumberOfRows + A.numberOfExternalValues;
	A.numberOfSendNeighbors = sendList.size();
	A.totalToBeSent = totalToBeSent;
	A.elementsToSend = elementsToSend;
	A.neighbors = neighbors;
	A.receiveLength = receiveLength;
	A.sendLength = sendLength;
	A.sendBuffer = sendBuffer;

#ifdef HPCG_DETAILED_DEBUG
	HPCG_fout << " For rank " << geom.rank << " of " << geom.size << ", number of neighbors = " << A.numberOfSendNeighbors << endl;
	for (int i = 0; i < A.numberOfSendNeighbors; i++) {
		HPCG_fout << "     rank " << geom.rank << " neighbor " << neighbors[i] << " send/recv length = " << sendLength[i] << "/" << receiveLength[i] << endl;
		for (local_int_t j = 0; j<sendLength[i]; ++j)
			HPCG_fout << "       rank " << geom.rank << " elementsToSend[" << j << "] = " << elementsToSend[j] << endl;
	}
#endif

#endif // ifndef HPCG_NOMPI

	return;
}
<|endoftext|>


<commit_before>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * \file opt_dead_code.cpp
 *
 * Eliminates dead assignments and variable declarations from the code.
 */

#include "ir.h"
#include "ir_visitor.h"
#include "ir_variable_refcount.h"
#include "glsl_types.h"

static bool debug = false;

/**
 * Do a dead code pass over instructions and everything that instructions
 * references.
 *
 * Note that this will remove assignments to globals, so it is not suitable
 * for usage on an unlinked instruction stream.
 */
bool
do_dead_code(exec_list *instructions, bool uniform_locations_assigned)
{
   ir_variable_refcount_visitor v;
   bool progress = false;

   v.run(instructions);

   foreach_iter(exec_list_iterator, iter, v.variable_list) {
      ir_variable_refcount_entry *entry = (ir_variable_refcount_entry *)iter.get();

      /* Since each assignment is a reference, the refereneced count must be
       * greater than or equal to the assignment count.  If they are equal,
       * then all of the references are assignments, and the variable is
       * dead.
       *
       * Note that if the variable is neither assigned nor referenced, both
       * counts will be zero and will be caught by the equality test.
       */
      assert(entry->referenced_count >= entry->assigned_count);

      if (debug) {
	 printf("%s@%p: %d refs, %d assigns, %sdeclared in our scope\n",
		entry->var->name, (void *) entry->var,
		entry->referenced_count, entry->assigned_count,
		entry->declaration ? "" : "not ");
      }

      if ((entry->referenced_count > entry->assigned_count)
	  || !entry->declaration)
	 continue;

      if (entry->assign) {
	 /* Remove a single dead assignment to the variable we found.
	  * Don't do so if it's a shader output, though.
	  */
	 if (entry->var->mode != ir_var_out &&
	     entry->var->mode != ir_var_inout) {
	    entry->assign->remove();
	    progress = true;

	    if (debug) {
	       printf("Removed assignment to %s@%p\n",
		      entry->var->name, (void *) entry->var);
	    }
	 }
      } else {
	 /* If there are no assignments or references to the variable left,
	  * then we can remove its declaration.
	  */

	 /* uniform initializers are precious, and could get used by another
	  * stage.  Also, once uniform locations have been assigned, the
	  * declaration cannot be deleted.
	  */
	 if (entry->var->mode == ir_var_uniform &&
	     (uniform_locations_assigned || entry->var->constant_value))
	    continue;

	 entry->var->remove();
	 progress = true;

	 if (debug) {
	    printf("Removed declaration of %s@%p\n",
		   entry->var->name, (void *) entry->var);
	 }
      }
   }

   return progress;
}

/**
 * Does a dead code pass on the functions present in the instruction stream.
 *
 * This is suitable for use while the program is not linked, as it will
 * ignore variable declarations (and the assignments to them) for variables
 * with global scope.
 */
bool
do_dead_code_unlinked(exec_list *instructions)
{
   bool progress = false;

   foreach_iter(exec_list_iterator, iter, *instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      ir_function *f = ir->as_function();
      if (f) {
	 foreach_iter(exec_list_iterator, sigiter, *f) {
	    ir_function_signature *sig =
	       (ir_function_signature *) sigiter.get();
	    /* The setting of the uniform_locations_assigned flag here is
	     * irrelevent.  If there is a uniform declaration encountered
	     * inside the body of the function, something has already gone
	     * terribly, terribly wrong.
	     */
	    if (do_dead_code(&sig->body, false))
	       progress = true;
	 }
      }
   }

   return progress;
}
<commit_msg>glsl: Don't dead-code eliminiate uniforms declared in uniform blocks.<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * \file opt_dead_code.cpp
 *
 * Eliminates dead assignments and variable declarations from the code.
 */

#include "ir.h"
#include "ir_visitor.h"
#include "ir_variable_refcount.h"
#include "glsl_types.h"

static bool debug = false;

/**
 * Do a dead code pass over instructions and everything that instructions
 * references.
 *
 * Note that this will remove assignments to globals, so it is not suitable
 * for usage on an unlinked instruction stream.
 */
bool
do_dead_code(exec_list *instructions, bool uniform_locations_assigned)
{
   ir_variable_refcount_visitor v;
   bool progress = false;

   v.run(instructions);

   foreach_iter(exec_list_iterator, iter, v.variable_list) {
      ir_variable_refcount_entry *entry = (ir_variable_refcount_entry *)iter.get();

      /* Since each assignment is a reference, the refereneced count must be
       * greater than or equal to the assignment count.  If they are equal,
       * then all of the references are assignments, and the variable is
       * dead.
       *
       * Note that if the variable is neither assigned nor referenced, both
       * counts will be zero and will be caught by the equality test.
       */
      assert(entry->referenced_count >= entry->assigned_count);

      if (debug) {
	 printf("%s@%p: %d refs, %d assigns, %sdeclared in our scope\n",
		entry->var->name, (void *) entry->var,
		entry->referenced_count, entry->assigned_count,
		entry->declaration ? "" : "not ");
      }

      if ((entry->referenced_count > entry->assigned_count)
	  || !entry->declaration)
	 continue;

      if (entry->assign) {
	 /* Remove a single dead assignment to the variable we found.
	  * Don't do so if it's a shader output, though.
	  */
	 if (entry->var->mode != ir_var_out &&
	     entry->var->mode != ir_var_inout) {
	    entry->assign->remove();
	    progress = true;

	    if (debug) {
	       printf("Removed assignment to %s@%p\n",
		      entry->var->name, (void *) entry->var);
	    }
	 }
      } else {
	 /* If there are no assignments or references to the variable left,
	  * then we can remove its declaration.
	  */

	 /* uniform initializers are precious, and could get used by another
	  * stage.  Also, once uniform locations have been assigned, the
	  * declaration cannot be deleted.
	  *
	  * Also, GL_ARB_uniform_buffer_object says that std140
	  * uniforms will not be eliminated.  Since we always do
	  * std140, just don't eliminate uniforms in UBOs.
	  */
	 if (entry->var->mode == ir_var_uniform &&
	     (uniform_locations_assigned ||
	      entry->var->constant_value ||
	      entry->var->uniform_block != -1))
	    continue;

	 entry->var->remove();
	 progress = true;

	 if (debug) {
	    printf("Removed declaration of %s@%p\n",
		   entry->var->name, (void *) entry->var);
	 }
      }
   }

   return progress;
}

/**
 * Does a dead code pass on the functions present in the instruction stream.
 *
 * This is suitable for use while the program is not linked, as it will
 * ignore variable declarations (and the assignments to them) for variables
 * with global scope.
 */
bool
do_dead_code_unlinked(exec_list *instructions)
{
   bool progress = false;

   foreach_iter(exec_list_iterator, iter, *instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      ir_function *f = ir->as_function();
      if (f) {
	 foreach_iter(exec_list_iterator, sigiter, *f) {
	    ir_function_signature *sig =
	       (ir_function_signature *) sigiter.get();
	    /* The setting of the uniform_locations_assigned flag here is
	     * irrelevent.  If there is a uniform declaration encountered
	     * inside the body of the function, something has already gone
	     * terribly, terribly wrong.
	     */
	    if (do_dead_code(&sig->body, false))
	       progress = true;
	 }
      }
   }

   return progress;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "multivaluerange.h"
#include "multivalue.h"
#include "length.h"
#include "serialise.h"

MultipleValueRange::MultipleValueRange(Xapian::valueno slot_, const std::string &start_, const std::string &end_)
	: ValuePostingSource(slot_), slot(slot_), start(start_), end(end_) {
	set_maxweight(1.0);
}

// Receive start and end did not serialize.
Xapian::Query
MultipleValueRange::getQuery(Xapian::valueno slot_, char field_type, std::string start_, std::string end_, const std::string &field_name) {
	if (start_.empty() && end_.empty()){
		return Xapian::Query::MatchAll;
	} else if (start_.empty()) {
		end_ = Serialise::serialise(field_type, end_);
		if (end_.empty()) throw Xapian::QueryParserError("Failed to serialize '" + field_name + "'");
		MultipleValueLE mvle(slot_, end_);
		return Xapian::Query(&mvle);
	} else if (end_.empty()) {
		start_ = Serialise::serialise(field_type, start_);
		if (start_.empty()) throw Xapian::QueryParserError("Failed to serialize '" + field_name + "'");
		MultipleValueGE mvge(slot_, start_);
		return Xapian::Query(&mvge);
	}

	// Multiple Value Range
	start_ = Serialise::serialise(field_type, start_);
	if (start_.empty()) throw Xapian::QueryParserError("Failed to serialize '" + field_name + "'");
	end_ = Serialise::serialise(field_type, end_);
	if (end_.empty()) throw Xapian::QueryParserError("Failed to serialize '" + field_name + "'");
	if (start_ > end_) return Xapian::Query::MatchNothing;
	MultipleValueRange mvr(slot_, start_, end_);
	return Xapian::Query(&mvr);
}

bool
MultipleValueRange::insideRange() {
	StringList list;
	list.unserialise(*value_it);
	StringList::const_iterator i(list.begin());
	for ( ; i != list.end(); i++) {
		if (*i >= start && *i <= end) {
			return true;
		}
	}
	return false;
}

void
MultipleValueRange::next(double min_wt) {
	Xapian::ValuePostingSource::next(min_wt);
	while (value_it != db.valuestream_end(slot)) {
		if (insideRange()) break;
		++value_it;
	}
}

void
MultipleValueRange::skip_to(Xapian::docid min_docid, double min_wt) {
	Xapian::ValuePostingSource::skip_to(min_docid, min_wt);
	while (value_it != db.valuestream_end(slot)) {
		if (insideRange()) break;
		++value_it;
	}
}

bool
MultipleValueRange::check(Xapian::docid min_docid, double min_wt) {
	if (!ValuePostingSource::check(min_docid, min_wt)) {
		// check returned false, so we know the document is not in the source.
		return false;
	}

	if (value_it == db.valuestream_end(slot)) {
		// return true, since we're definitely at the end of the list.
		return true;
	}

	return insideRange();
}

double
MultipleValueRange::get_weight() const {
	return 1.0;
}

MultipleValueRange*
MultipleValueRange::clone() const {
	return new MultipleValueRange(slot, start, end);
}

std::string
MultipleValueRange::name() const {
	return "MultipleValueRange";
}

std::string
MultipleValueRange::serialise() const {
	std::string serialised, values, s_slot(Xapian::sortable_serialise(slot));
	values.append(encode_length(s_slot.size()));
	values.append(s_slot);
	values.append(encode_length(start.size()));
	values.append(start);
	values.append(encode_length(end.size()));
	values.append(end);
	serialised.append(encode_length(values.size()));
	serialised.append(values);
	return serialised;
}

MultipleValueRange*
MultipleValueRange::unserialise_with_registry(const std::string &s, const Xapian::Registry &) const {
	StringList data;
	data.unserialise(s);
	return new MultipleValueRange(Xapian::sortable_unserialise(data.at(0)), data.at(1), data.at(2));
}

void
MultipleValueRange::init(const Xapian::Database &db_) {
	Xapian::ValuePostingSource::init(db_);

	// Possible that no documents are in range.
	termfreq_min = 0;
}

std::string
MultipleValueRange::get_description() const {
	std::string result("MultipleValueRange ");
	result += std::to_string(slot) + " " + start;
	result += " " + end;
	return result;
}

MultipleValueGE::MultipleValueGE(Xapian::valueno slot_, const std::string &start_)
	: ValuePostingSource(slot_), slot(slot_), start(start_) {
	set_maxweight(1.0);
}

bool
MultipleValueGE::insideRange() {
	StringList list;
	list.unserialise(*value_it);
	StringList::const_iterator i(list.begin());
	for ( ; i != list.end(); i++) {
		if (*i >= start) {
			return true;
		}
	}
	return false;
}

void
MultipleValueGE::next(double min_wt) {
	Xapian::ValuePostingSource::next(min_wt);
	while (value_it != db.valuestream_end(slot)) {
		if (insideRange()) break;
		++value_it;
	}
}

void
MultipleValueGE::skip_to(Xapian::docid min_docid, double min_wt) {
	Xapian::ValuePostingSource::skip_to(min_docid, min_wt);
	while (value_it != db.valuestream_end(slot)) {
		if (insideRange()) break;
		++value_it;
	}
}

bool
MultipleValueGE::check(Xapian::docid min_docid, double min_wt) {
	if (!ValuePostingSource::check(min_docid, min_wt)) {
		// check returned false, so we know the document is not in the source.
		return false;
	}

	if (value_it == db.valuestream_end(slot)) {
		// return true, since we're definitely at the end of the list.
		return true;
	}

	return insideRange();
}

double
MultipleValueGE::get_weight() const {
	return 1.0;
}

MultipleValueGE*
MultipleValueGE::clone() const {
	return new MultipleValueGE(slot, start);
}

std::string
MultipleValueGE::name() const {
	return "MultipleValueGE";
}

std::string
MultipleValueGE::serialise() const {
	std::string serialised, values, s_slot(Xapian::sortable_serialise(slot));
	values.append(encode_length(s_slot.size()));
	values.append(s_slot);
	values.append(encode_length(start.size()));
	values.append(start);
	serialised.append(encode_length(values.size()));
	serialised.append(values);
	return serialised;
}

MultipleValueGE*
MultipleValueGE::unserialise_with_registry(const std::string &s, const Xapian::Registry &) const {
	StringList data;
	data.unserialise(s);
	return new MultipleValueGE(Xapian::sortable_unserialise(data.at(0)), data.at(1));
}

void
MultipleValueGE::init(const Xapian::Database &db_) {
	Xapian::ValuePostingSource::init(db_);

	// Possible that no documents are in range.
	termfreq_min = 0;
}

std::string
MultipleValueGE::get_description() const {
	std::string result("MultipleValueGE ");
	result += std::to_string(slot) + " " + start + ")";
	return result;
}

MultipleValueLE::MultipleValueLE(Xapian::valueno slot_, const std::string &end_)
	: ValuePostingSource(slot_), slot(slot_), end(end_) {
	set_maxweight(1.0);
}

bool
MultipleValueLE::insideRange() {
	StringList list;
	list.unserialise(*value_it);
	StringList::const_iterator i(list.begin());
	for ( ; i != list.end(); i++) {
		if (*i <= end) {
			return true;
		}
	}
	return false;
}

void
MultipleValueLE::next(double min_wt) {
	Xapian::ValuePostingSource::next(min_wt);
	while (value_it != db.valuestream_end(slot)) {
		if (insideRange()) break;
		++value_it;
	}
}

void
MultipleValueLE::skip_to(Xapian::docid min_docid, double min_wt) {
	Xapian::ValuePostingSource::skip_to(min_docid, min_wt);
	while (value_it != db.valuestream_end(slot)) {
		if (insideRange()) break;
		++value_it;
	}
}

bool
MultipleValueLE::check(Xapian::docid min_docid, double min_wt) {
	if (!ValuePostingSource::check(min_docid, min_wt)) {
		// check returned false, so we know the document is not in the source.
		return false;
	}

	if (value_it == db.valuestream_end(slot)) {
		// return true, since we're definitely at the end of the list.
		return true;
	}

	return insideRange();
}

double
MultipleValueLE::get_weight() const {
	return 1.0;
}

MultipleValueLE*
MultipleValueLE::clone() const {
	return new MultipleValueLE(slot, end);
}

std::string
MultipleValueLE::name() const {
	return "MultipleValueLE";
}

std::string
MultipleValueLE::serialise() const {
	std::string serialised, values, s_slot(Xapian::sortable_serialise(slot));
	values.append(encode_length(s_slot.size()));
	values.append(s_slot);
	values.append(encode_length(end.size()));
	values.append(end);
	serialised.append(encode_length(values.size()));
	serialised.append(values);
	return serialised;
}

MultipleValueLE*
MultipleValueLE::unserialise_with_registry(const std::string &s, const Xapian::Registry &) const {
	StringList data;
	data.unserialise(s);
	return new MultipleValueLE(Xapian::sortable_unserialise(data.at(0)), data.at(1));
}

void
MultipleValueLE::init(const Xapian::Database &db_) {
	Xapian::ValuePostingSource::init(db_);

	// Possible that no documents are in range.
	termfreq_min = 0;
}

std::string
MultipleValueLE::get_description() const {
	std::string result("MultipleValueLE ");
	result += std::to_string(slot) + " " + end + ")";
	return result;
}<commit_msg>Initialization of parameters in right order<commit_after>/*
 * Copyright (C) 2015 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "multivaluerange.h"
#include "multivalue.h"
#include "length.h"
#include "serialise.h"

MultipleValueRange::MultipleValueRange(Xapian::valueno slot_, const std::string &start_, const std::string &end_)
	: ValuePostingSource(slot_), start(start_), end(end_), slot(slot_) {
	set_maxweight(1.0);
}

// Receive start and end did not serialize.
Xapian::Query
MultipleValueRange::getQuery(Xapian::valueno slot_, char field_type, std::string start_, std::string end_, const std::string &field_name) {
	if (start_.empty() && end_.empty()){
		return Xapian::Query::MatchAll;
	} else if (start_.empty()) {
		end_ = Serialise::serialise(field_type, end_);
		if (end_.empty()) throw Xapian::QueryParserError("Failed to serialize '" + field_name + "'");
		MultipleValueLE mvle(slot_, end_);
		return Xapian::Query(&mvle);
	} else if (end_.empty()) {
		start_ = Serialise::serialise(field_type, start_);
		if (start_.empty()) throw Xapian::QueryParserError("Failed to serialize '" + field_name + "'");
		MultipleValueGE mvge(slot_, start_);
		return Xapian::Query(&mvge);
	}

	// Multiple Value Range
	start_ = Serialise::serialise(field_type, start_);
	if (start_.empty()) throw Xapian::QueryParserError("Failed to serialize '" + field_name + "'");
	end_ = Serialise::serialise(field_type, end_);
	if (end_.empty()) throw Xapian::QueryParserError("Failed to serialize '" + field_name + "'");
	if (start_ > end_) return Xapian::Query::MatchNothing;
	MultipleValueRange mvr(slot_, start_, end_);
	return Xapian::Query(&mvr);
}

bool
MultipleValueRange::insideRange() {
	StringList list;
	list.unserialise(*value_it);
	StringList::const_iterator i(list.begin());
	for ( ; i != list.end(); i++) {
		if (*i >= start && *i <= end) {
			return true;
		}
	}
	return false;
}

void
MultipleValueRange::next(double min_wt) {
	Xapian::ValuePostingSource::next(min_wt);
	while (value_it != db.valuestream_end(slot)) {
		if (insideRange()) break;
		++value_it;
	}
}

void
MultipleValueRange::skip_to(Xapian::docid min_docid, double min_wt) {
	Xapian::ValuePostingSource::skip_to(min_docid, min_wt);
	while (value_it != db.valuestream_end(slot)) {
		if (insideRange()) break;
		++value_it;
	}
}

bool
MultipleValueRange::check(Xapian::docid min_docid, double min_wt) {
	if (!ValuePostingSource::check(min_docid, min_wt)) {
		// check returned false, so we know the document is not in the source.
		return false;
	}

	if (value_it == db.valuestream_end(slot)) {
		// return true, since we're definitely at the end of the list.
		return true;
	}

	return insideRange();
}

double
MultipleValueRange::get_weight() const {
	return 1.0;
}

MultipleValueRange*
MultipleValueRange::clone() const {
	return new MultipleValueRange(slot, start, end);
}

std::string
MultipleValueRange::name() const {
	return "MultipleValueRange";
}

std::string
MultipleValueRange::serialise() const {
	std::string serialised, values, s_slot(Xapian::sortable_serialise(slot));
	values.append(encode_length(s_slot.size()));
	values.append(s_slot);
	values.append(encode_length(start.size()));
	values.append(start);
	values.append(encode_length(end.size()));
	values.append(end);
	serialised.append(encode_length(values.size()));
	serialised.append(values);
	return serialised;
}

MultipleValueRange*
MultipleValueRange::unserialise_with_registry(const std::string &s, const Xapian::Registry &) const {
	StringList data;
	data.unserialise(s);
	return new MultipleValueRange(Xapian::sortable_unserialise(data.at(0)), data.at(1), data.at(2));
}

void
MultipleValueRange::init(const Xapian::Database &db_) {
	Xapian::ValuePostingSource::init(db_);

	// Possible that no documents are in range.
	termfreq_min = 0;
}

std::string
MultipleValueRange::get_description() const {
	std::string result("MultipleValueRange ");
	result += std::to_string(slot) + " " + start;
	result += " " + end;
	return result;
}

MultipleValueGE::MultipleValueGE(Xapian::valueno slot_, const std::string &start_)
	: ValuePostingSource(slot_), start(start_), slot(slot_) {
	set_maxweight(1.0);
}

bool
MultipleValueGE::insideRange() {
	StringList list;
	list.unserialise(*value_it);
	StringList::const_iterator i(list.begin());
	for ( ; i != list.end(); i++) {
		if (*i >= start) {
			return true;
		}
	}
	return false;
}

void
MultipleValueGE::next(double min_wt) {
	Xapian::ValuePostingSource::next(min_wt);
	while (value_it != db.valuestream_end(slot)) {
		if (insideRange()) break;
		++value_it;
	}
}

void
MultipleValueGE::skip_to(Xapian::docid min_docid, double min_wt) {
	Xapian::ValuePostingSource::skip_to(min_docid, min_wt);
	while (value_it != db.valuestream_end(slot)) {
		if (insideRange()) break;
		++value_it;
	}
}

bool
MultipleValueGE::check(Xapian::docid min_docid, double min_wt) {
	if (!ValuePostingSource::check(min_docid, min_wt)) {
		// check returned false, so we know the document is not in the source.
		return false;
	}

	if (value_it == db.valuestream_end(slot)) {
		// return true, since we're definitely at the end of the list.
		return true;
	}

	return insideRange();
}

double
MultipleValueGE::get_weight() const {
	return 1.0;
}

MultipleValueGE*
MultipleValueGE::clone() const {
	return new MultipleValueGE(slot, start);
}

std::string
MultipleValueGE::name() const {
	return "MultipleValueGE";
}

std::string
MultipleValueGE::serialise() const {
	std::string serialised, values, s_slot(Xapian::sortable_serialise(slot));
	values.append(encode_length(s_slot.size()));
	values.append(s_slot);
	values.append(encode_length(start.size()));
	values.append(start);
	serialised.append(encode_length(values.size()));
	serialised.append(values);
	return serialised;
}

MultipleValueGE*
MultipleValueGE::unserialise_with_registry(const std::string &s, const Xapian::Registry &) const {
	StringList data;
	data.unserialise(s);
	return new MultipleValueGE(Xapian::sortable_unserialise(data.at(0)), data.at(1));
}

void
MultipleValueGE::init(const Xapian::Database &db_) {
	Xapian::ValuePostingSource::init(db_);

	// Possible that no documents are in range.
	termfreq_min = 0;
}

std::string
MultipleValueGE::get_description() const {
	std::string result("MultipleValueGE ");
	result += std::to_string(slot) + " " + start + ")";
	return result;
}

MultipleValueLE::MultipleValueLE(Xapian::valueno slot_, const std::string &end_)
	: ValuePostingSource(slot_), end(end_), slot(slot_) {
	set_maxweight(1.0);
}

bool
MultipleValueLE::insideRange() {
	StringList list;
	list.unserialise(*value_it);
	StringList::const_iterator i(list.begin());
	for ( ; i != list.end(); i++) {
		if (*i <= end) {
			return true;
		}
	}
	return false;
}

void
MultipleValueLE::next(double min_wt) {
	Xapian::ValuePostingSource::next(min_wt);
	while (value_it != db.valuestream_end(slot)) {
		if (insideRange()) break;
		++value_it;
	}
}

void
MultipleValueLE::skip_to(Xapian::docid min_docid, double min_wt) {
	Xapian::ValuePostingSource::skip_to(min_docid, min_wt);
	while (value_it != db.valuestream_end(slot)) {
		if (insideRange()) break;
		++value_it;
	}
}

bool
MultipleValueLE::check(Xapian::docid min_docid, double min_wt) {
	if (!ValuePostingSource::check(min_docid, min_wt)) {
		// check returned false, so we know the document is not in the source.
		return false;
	}

	if (value_it == db.valuestream_end(slot)) {
		// return true, since we're definitely at the end of the list.
		return true;
	}

	return insideRange();
}

double
MultipleValueLE::get_weight() const {
	return 1.0;
}

MultipleValueLE*
MultipleValueLE::clone() const {
	return new MultipleValueLE(slot, end);
}

std::string
MultipleValueLE::name() const {
	return "MultipleValueLE";
}

std::string
MultipleValueLE::serialise() const {
	std::string serialised, values, s_slot(Xapian::sortable_serialise(slot));
	values.append(encode_length(s_slot.size()));
	values.append(s_slot);
	values.append(encode_length(end.size()));
	values.append(end);
	serialised.append(encode_length(values.size()));
	serialised.append(values);
	return serialised;
}

MultipleValueLE*
MultipleValueLE::unserialise_with_registry(const std::string &s, const Xapian::Registry &) const {
	StringList data;
	data.unserialise(s);
	return new MultipleValueLE(Xapian::sortable_unserialise(data.at(0)), data.at(1));
}

void
MultipleValueLE::init(const Xapian::Database &db_) {
	Xapian::ValuePostingSource::init(db_);

	// Possible that no documents are in range.
	termfreq_min = 0;
}

std::string
MultipleValueLE::get_description() const {
	std::string result("MultipleValueLE ");
	result += std::to_string(slot) + " " + end + ")";
	return result;
}<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2004-2006 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "audioplayer.h"
#include "mediaobject.h"
#include "audiopath.h"
#include "audiooutput.h"
#include <kurl.h>

namespace Phonon
{

class AudioPlayer::Private
{
	public:
		Private()
			: player( 0 )
		{
		}

		MediaObject* player;
		AudioPath* path;
		AudioOutput* output;
		KUrl url;

		void _k_stateChanged( Phonon::State, Phonon::State );
};

AudioPlayer::AudioPlayer( Phonon::Category category, QObject* parent )
	: QObject( parent )
	, d( new Private )
{
	d->output = new AudioOutput( category, this );
	d->path = new AudioPath( this );
	d->path->addOutput( d->output );
	d->player = new MediaObject( this );
	d->player->addAudioPath( d->path );

	connect( d->player, SIGNAL( _k_stateChanged( Phonon::State, Phonon::State ) ),
			SLOT( _k_stateChanged( Phonon::State, Phonon::State ) ) );
	connect( d->player, SIGNAL( finished() ), SIGNAL( finished() ) );
}

AudioPlayer::~AudioPlayer()
{
	delete d->player;
	delete d->path;
	delete d->output;
}

void AudioPlayer::load( const KUrl& url )
{
	// new URL
	d->player->setUrl( url );
	d->url = url;
}

void AudioPlayer::play( const KUrl& url )
{
	if( url == d->url )
	{
		if( !isPlaying() )
			d->player->play();
		return;
	}
	// new URL
	d->player->setUrl( url );

	if( ErrorState == d->player->state() )
		return;

	d->url = url;

	if( StoppedState == d->player->state() )
		d->player->play();
}

void AudioPlayer::play()
{
	play( d->url );
}

void AudioPlayer::pause()
{
	d->player->pause();
}

void AudioPlayer::stop()
{
	d->player->stop();
}

qint64 AudioPlayer::totalTime() const
{
	return d->player->totalTime();
}

qint64 AudioPlayer::currentTime() const
{
	return d->player->currentTime();
}

void AudioPlayer::seek( qint64 ms )
{
	d->player->seek( ms );
}

float AudioPlayer::volume() const
{
	return d->output->volume();
}

void AudioPlayer::setVolume( float v )
{
	d->output->setVolume( v );
}

bool AudioPlayer::isPlaying() const
{
	return ( d->player->state() == PlayingState );
}

bool AudioPlayer::isPaused() const
{
	return ( d->player->state() == PausedState );
}

void AudioPlayer::Private::_k_stateChanged( State ns, State os )
{
	if( os == LoadingState && ns == StoppedState )
		player->play();
}

} // namespaces

#include "audioplayer.moc"

// vim: sw=4 ts=4
<commit_msg>fix connection - I have to rethink whether this one is wanted, though<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2004-2006 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "audioplayer.h"
#include "mediaobject.h"
#include "audiopath.h"
#include "audiooutput.h"
#include <kurl.h>

namespace Phonon
{

class AudioPlayer::Private
{
	public:
		Private()
			: player( 0 )
		{
		}

		MediaObject* player;
		AudioPath* path;
		AudioOutput* output;
		KUrl url;

		void _k_stateChanged( Phonon::State, Phonon::State );
};

AudioPlayer::AudioPlayer( Phonon::Category category, QObject* parent )
	: QObject( parent )
	, d( new Private )
{
	d->output = new AudioOutput( category, this );
	d->path = new AudioPath( this );
	d->path->addOutput( d->output );
	d->player = new MediaObject( this );
	d->player->addAudioPath( d->path );

    connect(d->player, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
            SLOT(_k_stateChanged(Phonon::State, Phonon::State)));
	connect( d->player, SIGNAL( finished() ), SIGNAL( finished() ) );
}

AudioPlayer::~AudioPlayer()
{
	delete d->player;
	delete d->path;
	delete d->output;
}

void AudioPlayer::load( const KUrl& url )
{
	// new URL
	d->player->setUrl( url );
	d->url = url;
}

void AudioPlayer::play( const KUrl& url )
{
	if( url == d->url )
	{
		if( !isPlaying() )
			d->player->play();
		return;
	}
	// new URL
	d->player->setUrl( url );

	if( ErrorState == d->player->state() )
		return;

	d->url = url;

	if( StoppedState == d->player->state() )
		d->player->play();
}

void AudioPlayer::play()
{
	play( d->url );
}

void AudioPlayer::pause()
{
	d->player->pause();
}

void AudioPlayer::stop()
{
	d->player->stop();
}

qint64 AudioPlayer::totalTime() const
{
	return d->player->totalTime();
}

qint64 AudioPlayer::currentTime() const
{
	return d->player->currentTime();
}

void AudioPlayer::seek( qint64 ms )
{
	d->player->seek( ms );
}

float AudioPlayer::volume() const
{
	return d->output->volume();
}

void AudioPlayer::setVolume( float v )
{
	d->output->setVolume( v );
}

bool AudioPlayer::isPlaying() const
{
	return ( d->player->state() == PlayingState );
}

bool AudioPlayer::isPaused() const
{
	return ( d->player->state() == PausedState );
}

void AudioPlayer::Private::_k_stateChanged( State ns, State os )
{
	if( os == LoadingState && ns == StoppedState )
		player->play();
}

} // namespaces

#include "audioplayer.moc"

// vim: sw=4 ts=4
<|endoftext|>


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

#include "searchpersistent.h"

#include "akonadi.h"
#include "akonadiconnection.h"
#include "response.h"
#include "storage/datastore.h"
#include "storage/entity.h"
#include "storage/transaction.h"
#include "handlerhelper.h"
#include "search/searchmanager.h"
#include "imapstreamparser.h"
#include "libs/protocol_p.h"
#include <akdebug.h>

#include <QtCore/QStringList>
#include <qdbusinterface.h>
#include <QtDBus/qdbusreply.h>

using namespace Akonadi;

SearchPersistent::SearchPersistent()
  : Handler()
{
}

SearchPersistent::~SearchPersistent()
{
}

bool SearchPersistent::parseStream()
{
  QString collectionName = m_streamParser->readUtf8String();
  if ( collectionName.isEmpty() )
    return failureResponse( "No name specified" );

  DataStore *db = connection()->storageBackend();
  Transaction transaction( db );

  const QString queryString = m_streamParser->readUtf8String();
  if ( queryString.isEmpty() )
    return failureResponse( "No query specified" );

  // for legacy clients we have to guess the language
#ifdef AKONADI_USE_STRIGI_SEARCH
  QString lang = QLatin1String( "XESAM" );
#else
  QString lang = QLatin1String( "SPARQL" );
#endif

  if ( m_streamParser->hasList() ) {
    m_streamParser->beginList();
    while ( !m_streamParser->atListEnd() ) {
      const QByteArray key = m_streamParser->readString();
      if ( key == AKONADI_PARAM_PERSISTENTSEARCH_QUERYLANG ) {
        lang = m_streamParser->readUtf8String();
      }
    }
  }

  Collection col;
  col.setQueryString( queryString );
  col.setQueryLanguage( lang );
  col.setRemoteId( queryString ); // ### remove, legacy compat
  col.setParentId( 1 ); // search root
  col.setResourceId( 1 ); // search resource
  col.setName( collectionName );
  col.setIsVirtual( true );
  if ( !db->appendCollection( col ) )
    return failureResponse( "Unable to create persistent search" );

  if ( !db->addCollectionAttribute( col, "AccessRights", "luD" ) )
    return failureResponse( "Unable to set rights attribute on persistent search" );

  // work around the fact that we have no clue what might be in there
  MimeType::List mts = MimeType::retrieveAll();
  Q_FOREACH ( const MimeType &mt, mts ) {
    if ( mt.name() == QLatin1String( "inode/directory" ) )
      continue;
    col.addMimeType( mt );
  }

  if ( !transaction.commit() )
    return failureResponse( "Unable to commit transaction" );

  if ( !SearchManager::instance()->addSearch( col ) )
    return failureResponse( "Unable to add search to search manager" );

  const QByteArray b = HandlerHelper::collectionToByteArray( col );

  Response colResponse;
  colResponse.setUntagged();
  colResponse.setString( b );
  Q_EMIT responseAvailable( colResponse );

  return successResponse( "SEARCH_STORE completed" );
}

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

#include "searchpersistent.h"

#include "akonadi.h"
#include "akonadiconnection.h"
#include "response.h"
#include "storage/datastore.h"
#include "storage/entity.h"
#include "storage/transaction.h"
#include "handlerhelper.h"
#include "search/searchmanager.h"
#include "imapstreamparser.h"
#include "libs/protocol_p.h"
#include <akdebug.h>

#include <QtCore/QStringList>
#include <qdbusinterface.h>
#include <QtDBus/qdbusreply.h>

using namespace Akonadi;

SearchPersistent::SearchPersistent()
  : Handler()
{
}

SearchPersistent::~SearchPersistent()
{
}

bool SearchPersistent::parseStream()
{
  QString collectionName = m_streamParser->readUtf8String();
  if ( collectionName.isEmpty() ) {
    return failureResponse( "No name specified" );
  }

  DataStore *db = connection()->storageBackend();
  Transaction transaction( db );

  const QString queryString = m_streamParser->readUtf8String();
  if ( queryString.isEmpty() ) {
    return failureResponse( "No query specified" );
  }

  // for legacy clients we have to guess the language
#ifdef AKONADI_USE_STRIGI_SEARCH
  QString lang = QLatin1String( "XESAM" );
#else
  QString lang = QLatin1String( "SPARQL" );
#endif

  if ( m_streamParser->hasList() ) {
    m_streamParser->beginList();
    while ( !m_streamParser->atListEnd() ) {
      const QByteArray key = m_streamParser->readString();
      if ( key == AKONADI_PARAM_PERSISTENTSEARCH_QUERYLANG ) {
        lang = m_streamParser->readUtf8String();
      }
    }
  }

  Collection col;
  col.setQueryString( queryString );
  col.setQueryLanguage( lang );
  col.setRemoteId( queryString ); // ### remove, legacy compat
  col.setParentId( 1 ); // search root
  col.setResourceId( 1 ); // search resource
  col.setName( collectionName );
  col.setIsVirtual( true );
  if ( !db->appendCollection( col ) ) {
    return failureResponse( "Unable to create persistent search" );
  }

  if ( !db->addCollectionAttribute( col, "AccessRights", "luD" ) ) {
    return failureResponse( "Unable to set rights attribute on persistent search" );
  }

  // work around the fact that we have no clue what might be in there
  MimeType::List mts = MimeType::retrieveAll();
  Q_FOREACH ( const MimeType &mt, mts ) {
    if ( mt.name() == QLatin1String( "inode/directory" ) ) {
      continue;
    }
    col.addMimeType( mt );
  }

  if ( !transaction.commit() ) {
    return failureResponse( "Unable to commit transaction" );
  }

  if ( !SearchManager::instance()->addSearch( col ) ) {
    return failureResponse( "Unable to add search to search manager" );
  }

  const QByteArray b = HandlerHelper::collectionToByteArray( col );

  Response colResponse;
  colResponse.setUntagged();
  colResponse.setString( b );
  Q_EMIT responseAvailable( colResponse );

  return successResponse( "SEARCH_STORE completed" );
}
<|endoftext|>


<commit_before>#include <list>

#include <Poco/Exception.h>
#include <Poco/StringTokenizer.h>
#include <Poco/JSON/PrintHandler.h>

#include "di/Injectable.h"
#include "model/Sensor.h"
#include "model/User.h"
#include "model/ValueAt.h"
#include "rest/RestFlow.h"
#include "rest/RestLinker.h"
#include "restui/RestValueConsumer.h"
#include "restui/SensorRestHandler.h"
#include "restui/Serializing.h"
#include "util/Sanitize.h"

BEEEON_OBJECT_BEGIN(BeeeOn, RestUI, SensorRestHandler)
BEEEON_OBJECT_CASTABLE(RestHandler)
BEEEON_OBJECT_REF("sensorService", &SensorRestHandler::setSensorService)
BEEEON_OBJECT_REF("sensorHistoryService", &SensorRestHandler::setSensorHistoryService)
BEEEON_OBJECT_END(BeeeOn, RestUI, SensorRestHandler)

using namespace std;
using namespace Poco;
using namespace Poco::JSON;
using namespace BeeeOn;
using namespace BeeeOn::RestUI;

SensorRestHandler::SensorRestHandler():
	JSONRestHandler("sensors")
{
	registerAction<SensorRestHandler>("list", &SensorRestHandler::list, {"gateway_id", "device_id"});
	registerAction<SensorRestHandler>("detail", &SensorRestHandler::detail, {"gateway_id", "device_id", "sensor_id"});
	registerAction<SensorRestHandler>("current", &SensorRestHandler::current, {"gateway_id", "device_id", "sensor_id"});
	registerAction<SensorRestHandler>("history", &SensorRestHandler::history, {"gateway_id", "device_id", "sensor_id"});
}

void SensorRestHandler::setSensorService(SensorService::Ptr service)
{
	m_sensorService = service;
}

void SensorRestHandler::setSensorHistoryService(SensorHistoryService::Ptr service)
{
	m_sensorHistoryService = service;
}

void SensorRestHandler::list(RestFlow &flow)
{
	User user(flow.session()->userID());
	Gateway gateway(GatewayID::parse(flow.param("gateway_id")));
	Device device(DeviceID::parse(flow.param("device_id")));
	device.setGateway(gateway);
	std::list<Sensor> sensors;
	Relation<std::list<Sensor>, Device> data(sensors, device);
	data.setUser(user);

	m_sensorService->fetchMany(data);

	PrintHandler result(flow.response().stream());
	beginSuccess(result, 200);
	serialize(result, *flow.translator(), sensors);
	endSuccess(result);
}

void SensorRestHandler::prepareDetail(RestFlow &flow, Sensor &sensor)
{
	User user(flow.session()->userID());

	Gateway gateway(GatewayID::parse(flow.param("gateway_id")));
	Device device(DeviceID::parse(flow.param("device_id")));
	device.setGateway(gateway);
	sensor.setId(SensorID::parse(flow.param("sensor_id")));

	Relation<Sensor, Device> data(sensor, device);
	data.setUser(user);

	if (!m_sensorService->fetch(data))
		throw NotFoundException("no such sensor " + sensor);
}

void SensorRestHandler::detail(RestFlow &flow)
{
	Sensor sensor;
	prepareDetail(flow, sensor);

	PrintHandler result(flow.response().stream());
	beginSuccess(result, 200);
	serialize(result, *flow.translator(), sensor);
	endSuccess(result);
}

void SensorRestHandler::current(RestFlow &flow)
{
	Sensor sensor;
	prepareDetail(flow, sensor);

	PrintHandler result(flow.response().stream());
	beginSuccess(result, 200);

	if (sensor.at().isNull()) {
		result.null();
	}
	else {
		RestValueConsumer consumer(result);
		consumer.begin(*sensor.info().type());
		consumer.single(ValueAt(sensor.at().value(), sensor.value()));
		consumer.end();
	}

	endSuccess(result);
}

TimeInterval SensorRestHandler::parseRange(const string &input) const
{
	if (input == "hour")
		return TimeInterval::past(1 * Timespan::HOURS);
	if (input == "day")
		return TimeInterval::past(1 * Timespan::DAYS);
	if (input == "week")
		return TimeInterval::past(7 * Timespan::DAYS);
	if (input == "month")
		return TimeInterval::past(30 * Timespan::DAYS);

	StringTokenizer range(input, ",",
		StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY);

	if (range.count() == 1) {
		const Timespan seconds =
			NumberParser::parseUnsigned64(range[0]) * Timespan::SECONDS;
		return TimeInterval::past(seconds);
	}
	else if (range.count() == 2) {
		const Timestamp start = Timestamp::fromEpochTime(
			NumberParser::parseUnsigned64(range[0]));
		const Timestamp end = Timestamp::fromEpochTime(
			NumberParser::parseUnsigned64(range[1]));

		return TimeInterval(start, end);
	}

	throw InvalidArgumentException("invalid range: " + input);
}

Timespan SensorRestHandler::parseInterval(const string &input) const
{
	return NumberParser::parseUnsigned(input) * Timespan::SECONDS;
}

string SensorRestHandler::parseAggregation(const string &input) const
{
	if (input == "avg")
		return input;
	if (input == "min")
		return input;
	if (input == "max")
		return input;

	throw InvalidArgumentException("invalid aggregation: " + input);
}

void SensorRestHandler::history(RestFlow &flow)
{
	User user(flow.session()->userID());
	Gateway gateway(GatewayID::parse(flow.param("gateway_id")));
	Device device(DeviceID::parse(flow.param("device_id")));
	device.setGateway(gateway);
	ModuleInfo module;
	module.setId(ModuleInfoID::parse(flow.param("sensor_id")));
	Relation<ModuleInfo, Device> input(module, device);
	input.setUser(user);

	URI::QueryParameters queryParams = flow.uri().getQueryParameters();

	TimeInterval range = TimeInterval::past(1 * Timespan::HOURS);
	string aggregation = "avg";
	Timespan interval = 15 * Timespan::SECONDS;

	for (auto &item : queryParams) {
		if (item.first == "range")
			range = parseRange(Sanitize::common(item.second));
		else if (item.first == "aggregation")
			aggregation = parseAggregation(Sanitize::strict(item.second));
		else if (item.first == "interval")
			interval = parseInterval(Sanitize::strict(item.second));
		else
			throw InvalidArgumentException("unknown query parameter");
	}

	PrintHandler result(flow.response().stream());
	beginSuccess(result, 200);
	result.startArray();

	RestValueConsumer consumer(result);

	try {
		m_sensorHistoryService->fetchRange(input, range, interval, aggregation, consumer);
	}
	catch (...) {
		// in case of a failure, finish the probably incomplete result
		// to at least not break the client processing, it is too late
		// to signalize any failures
		result.endArray();
		endSuccess(result);

		throw; // log the failure by upper layers
	}

	result.endArray();
	endSuccess(result);
}

<commit_msg>SensorRestHandler: ignore unknown URI query parameters<commit_after>#include <list>

#include <Poco/Exception.h>
#include <Poco/StringTokenizer.h>
#include <Poco/JSON/PrintHandler.h>

#include "di/Injectable.h"
#include "model/Sensor.h"
#include "model/User.h"
#include "model/ValueAt.h"
#include "rest/RestFlow.h"
#include "rest/RestLinker.h"
#include "restui/RestValueConsumer.h"
#include "restui/SensorRestHandler.h"
#include "restui/Serializing.h"
#include "util/Sanitize.h"

BEEEON_OBJECT_BEGIN(BeeeOn, RestUI, SensorRestHandler)
BEEEON_OBJECT_CASTABLE(RestHandler)
BEEEON_OBJECT_REF("sensorService", &SensorRestHandler::setSensorService)
BEEEON_OBJECT_REF("sensorHistoryService", &SensorRestHandler::setSensorHistoryService)
BEEEON_OBJECT_END(BeeeOn, RestUI, SensorRestHandler)

using namespace std;
using namespace Poco;
using namespace Poco::JSON;
using namespace BeeeOn;
using namespace BeeeOn::RestUI;

SensorRestHandler::SensorRestHandler():
	JSONRestHandler("sensors")
{
	registerAction<SensorRestHandler>("list", &SensorRestHandler::list, {"gateway_id", "device_id"});
	registerAction<SensorRestHandler>("detail", &SensorRestHandler::detail, {"gateway_id", "device_id", "sensor_id"});
	registerAction<SensorRestHandler>("current", &SensorRestHandler::current, {"gateway_id", "device_id", "sensor_id"});
	registerAction<SensorRestHandler>("history", &SensorRestHandler::history, {"gateway_id", "device_id", "sensor_id"});
}

void SensorRestHandler::setSensorService(SensorService::Ptr service)
{
	m_sensorService = service;
}

void SensorRestHandler::setSensorHistoryService(SensorHistoryService::Ptr service)
{
	m_sensorHistoryService = service;
}

void SensorRestHandler::list(RestFlow &flow)
{
	User user(flow.session()->userID());
	Gateway gateway(GatewayID::parse(flow.param("gateway_id")));
	Device device(DeviceID::parse(flow.param("device_id")));
	device.setGateway(gateway);
	std::list<Sensor> sensors;
	Relation<std::list<Sensor>, Device> data(sensors, device);
	data.setUser(user);

	m_sensorService->fetchMany(data);

	PrintHandler result(flow.response().stream());
	beginSuccess(result, 200);
	serialize(result, *flow.translator(), sensors);
	endSuccess(result);
}

void SensorRestHandler::prepareDetail(RestFlow &flow, Sensor &sensor)
{
	User user(flow.session()->userID());

	Gateway gateway(GatewayID::parse(flow.param("gateway_id")));
	Device device(DeviceID::parse(flow.param("device_id")));
	device.setGateway(gateway);
	sensor.setId(SensorID::parse(flow.param("sensor_id")));

	Relation<Sensor, Device> data(sensor, device);
	data.setUser(user);

	if (!m_sensorService->fetch(data))
		throw NotFoundException("no such sensor " + sensor);
}

void SensorRestHandler::detail(RestFlow &flow)
{
	Sensor sensor;
	prepareDetail(flow, sensor);

	PrintHandler result(flow.response().stream());
	beginSuccess(result, 200);
	serialize(result, *flow.translator(), sensor);
	endSuccess(result);
}

void SensorRestHandler::current(RestFlow &flow)
{
	Sensor sensor;
	prepareDetail(flow, sensor);

	PrintHandler result(flow.response().stream());
	beginSuccess(result, 200);

	if (sensor.at().isNull()) {
		result.null();
	}
	else {
		RestValueConsumer consumer(result);
		consumer.begin(*sensor.info().type());
		consumer.single(ValueAt(sensor.at().value(), sensor.value()));
		consumer.end();
	}

	endSuccess(result);
}

TimeInterval SensorRestHandler::parseRange(const string &input) const
{
	if (input == "hour")
		return TimeInterval::past(1 * Timespan::HOURS);
	if (input == "day")
		return TimeInterval::past(1 * Timespan::DAYS);
	if (input == "week")
		return TimeInterval::past(7 * Timespan::DAYS);
	if (input == "month")
		return TimeInterval::past(30 * Timespan::DAYS);

	StringTokenizer range(input, ",",
		StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY);

	if (range.count() == 1) {
		const Timespan seconds =
			NumberParser::parseUnsigned64(range[0]) * Timespan::SECONDS;
		return TimeInterval::past(seconds);
	}
	else if (range.count() == 2) {
		const Timestamp start = Timestamp::fromEpochTime(
			NumberParser::parseUnsigned64(range[0]));
		const Timestamp end = Timestamp::fromEpochTime(
			NumberParser::parseUnsigned64(range[1]));

		return TimeInterval(start, end);
	}

	throw InvalidArgumentException("invalid range: " + input);
}

Timespan SensorRestHandler::parseInterval(const string &input) const
{
	return NumberParser::parseUnsigned(input) * Timespan::SECONDS;
}

string SensorRestHandler::parseAggregation(const string &input) const
{
	if (input == "avg")
		return input;
	if (input == "min")
		return input;
	if (input == "max")
		return input;

	throw InvalidArgumentException("invalid aggregation: " + input);
}

void SensorRestHandler::history(RestFlow &flow)
{
	User user(flow.session()->userID());
	Gateway gateway(GatewayID::parse(flow.param("gateway_id")));
	Device device(DeviceID::parse(flow.param("device_id")));
	device.setGateway(gateway);
	ModuleInfo module;
	module.setId(ModuleInfoID::parse(flow.param("sensor_id")));
	Relation<ModuleInfo, Device> input(module, device);
	input.setUser(user);

	URI::QueryParameters queryParams = flow.uri().getQueryParameters();

	TimeInterval range = TimeInterval::past(1 * Timespan::HOURS);
	string aggregation = "avg";
	Timespan interval = 15 * Timespan::SECONDS;

	for (auto &item : queryParams) {
		if (item.first == "range")
			range = parseRange(Sanitize::common(item.second));
		else if (item.first == "aggregation")
			aggregation = parseAggregation(Sanitize::strict(item.second));
		else if (item.first == "interval")
			interval = parseInterval(Sanitize::strict(item.second));
		else
			continue; // ignore unknown parameters
	}

	PrintHandler result(flow.response().stream());
	beginSuccess(result, 200);
	result.startArray();

	RestValueConsumer consumer(result);

	try {
		m_sensorHistoryService->fetchRange(input, range, interval, aggregation, consumer);
	}
	catch (...) {
		// in case of a failure, finish the probably incomplete result
		// to at least not break the client processing, it is too late
		// to signalize any failures
		result.endArray();
		endSuccess(result);

		throw; // log the failure by upper layers
	}

	result.endArray();
	endSuccess(result);
}

<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "GLTexture.h"

#include "../base/Exception.h"

namespace avg {

GLTexture::GLTexture(const IntPoint& size, PixelFormat pf, bool bMipmap,
        unsigned wrapSMode, unsigned wrapTMode)
    : m_Size(size),
      m_pf(pf)

{
    if (getGLType(m_pf) == GL_FLOAT && !isFloatFormatSupported()) {
        throw Exception(AVG_ERR_UNSUPPORTED,
                "Float textures not supported by OpenGL configuration.");
    }

    glGenTextures(1, &m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "GLTexture: glGenTextures()");
    glBindTexture(GL_TEXTURE_2D, m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "GLTexture: glBindTexture()");
    if (bMipmap) {
        glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    } else {
        glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    }
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapSMode);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapTMode);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_2D, 0, getGLInternalFormat(), m_Size.x, m_Size.y, 0,
            getGLFormat(m_pf), getGLType(m_pf), 0);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "GLTexture: glTexImage2D()");

}

GLTexture::~GLTexture()
{
    glBindTexture(GL_TEXTURE_2D, 0);
    glDeleteTextures(1, &m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "GLTexture: DeleteTextures()");
}

void GLTexture::activate(int textureUnit)
{
    // TODO: This should set the complete texture state.
    glproc::ActiveTexture(textureUnit);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "GLTexture::activate ActiveTexture()");
    glBindTexture(GL_TEXTURE_2D, m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "GLTexture::activate BindTexture()");
}

void GLTexture::generateMipmaps()
{
    activate();
    glproc::GenerateMipmap(GL_TEXTURE_2D);
}

const IntPoint& GLTexture::getSize() const
{
    return m_Size;
}

PixelFormat GLTexture::getPF() const
{
    return m_pf;
}

unsigned GLTexture::getID() const
{
    return m_TexID;
}

bool GLTexture::isFloatFormatSupported()
{
    return queryOGLExtension("GL_ARB_texture_float");
}

int GLTexture::getGLFormat(PixelFormat pf)
{
    switch (pf) {
        case I8:
        case I32F:
            return GL_LUMINANCE;
        case A8:
            return GL_ALPHA;
        case R8G8B8A8:
        case R8G8B8X8:
            return GL_RGBA;
        case B8G8R8A8:
        case B8G8R8X8:
        case R32G32B32A32F:
            return GL_BGRA;
        default:
            AVG_ASSERT(false);
            return 0;
    }
}

int GLTexture::getGLType(PixelFormat pf)
{
    switch (pf) {
        case I8:
        case A8:
        case R8G8B8A8:
        case R8G8B8X8:
        case B8G8R8A8:
        case B8G8R8X8:
            return GL_UNSIGNED_BYTE;
        case R32G32B32A32F:
        case I32F:
            return GL_FLOAT;
        default:
            AVG_ASSERT(false);
            return 0;
    }
}

int GLTexture::getGLInternalFormat() const
{
    switch (m_pf) {
        case I8:
            return GL_LUMINANCE;
        case I32F:
            return GL_LUMINANCE32F_ARB;
        case A8:
            return GL_ALPHA;
        case R8G8B8A8:
        case R8G8B8X8:
        case B8G8R8A8:
        case B8G8R8X8:
            return GL_RGBA;
        case R32G32B32A32F:
            return GL_RGBA32F_ARB;
        default:
            AVG_ASSERT(false);
            return 0;
    }
}

}
<commit_msg>Optimized Mac OS X RGBA texture uploads.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "GLTexture.h"

#include "../base/Exception.h"

namespace avg {

GLTexture::GLTexture(const IntPoint& size, PixelFormat pf, bool bMipmap,
        unsigned wrapSMode, unsigned wrapTMode)
    : m_Size(size),
      m_pf(pf)

{
    if (getGLType(m_pf) == GL_FLOAT && !isFloatFormatSupported()) {
        throw Exception(AVG_ERR_UNSUPPORTED,
                "Float textures not supported by OpenGL configuration.");
    }

    glGenTextures(1, &m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "GLTexture: glGenTextures()");
    glBindTexture(GL_TEXTURE_2D, m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "GLTexture: glBindTexture()");
    if (bMipmap) {
        glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    } else {
        glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    }
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapSMode);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapTMode);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_2D, 0, getGLInternalFormat(), m_Size.x, m_Size.y, 0,
            getGLFormat(m_pf), getGLType(m_pf), 0);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "GLTexture: glTexImage2D()");

}

GLTexture::~GLTexture()
{
    glBindTexture(GL_TEXTURE_2D, 0);
    glDeleteTextures(1, &m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "GLTexture: DeleteTextures()");
}

void GLTexture::activate(int textureUnit)
{
    // TODO: This should set the complete texture state.
    glproc::ActiveTexture(textureUnit);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "GLTexture::activate ActiveTexture()");
    glBindTexture(GL_TEXTURE_2D, m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "GLTexture::activate BindTexture()");
}

void GLTexture::generateMipmaps()
{
    activate();
    glproc::GenerateMipmap(GL_TEXTURE_2D);
}

const IntPoint& GLTexture::getSize() const
{
    return m_Size;
}

PixelFormat GLTexture::getPF() const
{
    return m_pf;
}

unsigned GLTexture::getID() const
{
    return m_TexID;
}

bool GLTexture::isFloatFormatSupported()
{
    return queryOGLExtension("GL_ARB_texture_float");
}

int GLTexture::getGLFormat(PixelFormat pf)
{
    switch (pf) {
        case I8:
        case I32F:
            return GL_LUMINANCE;
        case A8:
            return GL_ALPHA;
        case R8G8B8A8:
        case R8G8B8X8:
            return GL_RGBA;
        case B8G8R8A8:
        case B8G8R8X8:
        case R32G32B32A32F:
            return GL_BGRA;
        default:
            AVG_ASSERT(false);
            return 0;
    }
}

int GLTexture::getGLType(PixelFormat pf)
{
    switch (pf) {
        case I8:
        case A8:
            return GL_UNSIGNED_BYTE;
        case R8G8B8A8:
        case R8G8B8X8:
        case B8G8R8A8:
        case B8G8R8X8:
#ifdef __APPLE__
            return GL_UNSIGNED_INT_8_8_8_8_REV;
#else
            return GL_UNSIGNED_BYTE;
#endif
        case R32G32B32A32F:
        case I32F:
            return GL_FLOAT;
        default:
            AVG_ASSERT(false);
            return 0;
    }
}

int GLTexture::getGLInternalFormat() const
{
    switch (m_pf) {
        case I8:
            return GL_LUMINANCE;
        case I32F:
            return GL_LUMINANCE32F_ARB;
        case A8:
            return GL_ALPHA;
        case R8G8B8A8:
        case R8G8B8X8:
        case B8G8R8A8:
        case B8G8R8X8:
            return GL_RGBA;
        case R32G32B32A32F:
            return GL_RGBA32F_ARB;
        default:
            AVG_ASSERT(false);
            return 0;
    }
}

}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>

#include <boost/process.hpp>
#include <chrono>
#include <csignal>
#include <future>
#include <iostream>
#include <string>
#include <thread>

#include "config/config.h"
#include "http/httpclient.h"
#include "logging/logging.h"
#include "package_manager/packagemanagerfake.h"
#include "storage/sqlstorage.h"
#include "test_utils.h"
#include "uptane/tuf.h"

static const int die_after = 50;       // percent
static const int pause_duration = 20;  // seconds

std::string server;

static std::mutex pause_m;
static std::condition_variable cv;
static bool die = false;
static bool resumed = false;

Config config;

static void progress_cb(const Uptane::Target& target, const std::string& description, unsigned int progress) {
  (void)target;
  (void)description;
  std::cout << "progress: " << progress << std::endl;
  if (progress >= die_after) {
    std::lock_guard<std::mutex> lk(pause_m);
    die = true;
    cv.notify_all();
  }
  if (resumed) {
    EXPECT_GE(progress, die_after);
  }
}

void resume(const Uptane::Target& target) {
  std::shared_ptr<INvStorage> storage(new SQLStorage(config.storage, false));
  auto http = std::make_shared<HttpClient>();
  auto pacman = std::make_shared<PackageManagerFake>(config.pacman, config.bootloader, storage, http);
  api::FlowControlToken token;
  KeyManager keys(storage, config.keymanagerConfig());
  Uptane::Fetcher fetcher(config, http);

  resumed = true;
  bool res = pacman->fetchTarget(target, fetcher, keys, progress_cb, &token);

  EXPECT_TRUE(res);
}

void pause_and_die(const Uptane::Target& target) {
  std::shared_ptr<INvStorage> storage(new SQLStorage(config.storage, false));
  auto http = std::make_shared<HttpClient>();
  api::FlowControlToken token;
  auto pacman = std::make_shared<PackageManagerFake>(config.pacman, config.bootloader, storage, http);
  KeyManager keys(storage, config.keymanagerConfig());
  Uptane::Fetcher fetcher(config, http);

  std::promise<bool> download_promise;
  auto result = download_promise.get_future();

  std::thread([&target, &fetcher, &download_promise, &token, pacman, &keys]() {
    bool res = pacman->fetchTarget(target, fetcher, keys, progress_cb, &token);
    download_promise.set_value(res);
  })
      .detach();

  std::unique_lock<std::mutex> lk(pause_m);
  cv.wait(lk, [] { return die; });
  token.setPause(true);
  std::this_thread::sleep_for(std::chrono::seconds(pause_duration));
  std::raise(SIGKILL);
}

TEST(FetcherDeathTest, TestResumeBinary) {
  TemporaryDirectory temp_dir;
  config.storage.path = temp_dir.Path();

  Json::Value target_json;
  target_json["hashes"]["sha256"] = "dd7bd1c37a3226e520b8d6939c30991b1c08772d5dab62b381c3a63541dc629a";
  target_json["length"] = 100 * (1 << 20);

  Uptane::Target target("large_file", target_json);
  ASSERT_DEATH(pause_and_die(target), "");
  std::cout << "Fetcher died, retrying" << std::endl;
  resume(target);
}

#ifndef __NO_MAIN__
int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);

  logger_init();
  logger_set_threshold(boost::log::trivial::trace);

  std::string port = TestUtils::getFreePort();
  server = "http://127.0.0.1:" + port;
  config.uptane.repo_server = server;
  boost::process::child http_server_process("tests/fake_http_server/fake_test_server.py", port, "-f");
  TestUtils::waitForServer(server + "/");
  return RUN_ALL_TESTS();
}
#endif  // __NO_MAIN__
<commit_msg>Test nongraceful shutdown during binary download<commit_after>#include <gtest/gtest.h>

#include <boost/process.hpp>
#include <chrono>
#include <csignal>
#include <future>
#include <iostream>
#include <string>
#include <thread>

#include "config/config.h"
#include "http/httpclient.h"
#include "logging/logging.h"
#include "package_manager/packagemanagerfake.h"
#include "storage/sqlstorage.h"
#include "test_utils.h"
#include "uptane/tuf.h"

static const int die_after = 50;      // percent
static const int pause_duration = 2;  // seconds

std::string server;

static std::mutex pause_m;
static std::condition_variable cv;
static bool die = false;
static bool resumed = false;

Config config;

static void progress_cb(const Uptane::Target& target, const std::string& description, unsigned int progress) {
  (void)target;
  (void)description;
  std::cout << "progress: " << progress << std::endl;
  if (progress >= die_after) {
    std::lock_guard<std::mutex> lk(pause_m);
    die = true;
    cv.notify_all();
  }
  if (resumed) {
    EXPECT_GE(progress, die_after);
  }
}

void resume(const Uptane::Target& target) {
  std::shared_ptr<INvStorage> storage(new SQLStorage(config.storage, false));
  auto http = std::make_shared<HttpClient>();
  auto pacman = std::make_shared<PackageManagerFake>(config.pacman, config.bootloader, storage, http);
  api::FlowControlToken token;
  KeyManager keys(storage, config.keymanagerConfig());
  Uptane::Fetcher fetcher(config, http);

  resumed = true;
  bool res = pacman->fetchTarget(target, fetcher, keys, progress_cb, &token);

  EXPECT_TRUE(res);
}

void try_and_die(const Uptane::Target& target, bool graceful) {
  std::shared_ptr<INvStorage> storage(new SQLStorage(config.storage, false));
  auto http = std::make_shared<HttpClient>();
  api::FlowControlToken token;
  auto pacman = std::make_shared<PackageManagerFake>(config.pacman, config.bootloader, storage, http);
  KeyManager keys(storage, config.keymanagerConfig());
  Uptane::Fetcher fetcher(config, http);

  std::promise<bool> download_promise;
  auto result = download_promise.get_future();

  std::thread([&target, &fetcher, &download_promise, &token, pacman, &keys]() {
    bool res = pacman->fetchTarget(target, fetcher, keys, progress_cb, &token);
    download_promise.set_value(res);
  })
      .detach();

  std::unique_lock<std::mutex> lk(pause_m);
  cv.wait(lk, [] { return die; });
  if (graceful) {
    token.setPause(true);
    std::this_thread::sleep_for(std::chrono::seconds(pause_duration));
    std::raise(SIGTERM);
  } else {
    std::raise(SIGKILL);
  }
}

TEST(FetcherDeathTest, TestResumeAfterPause) {
  TemporaryDirectory temp_dir;
  config.storage.path = temp_dir.Path();

  Json::Value target_json;
  target_json["hashes"]["sha256"] = "dd7bd1c37a3226e520b8d6939c30991b1c08772d5dab62b381c3a63541dc629a";
  target_json["length"] = 100 * (1 << 20);

  Uptane::Target target("large_file", target_json);
  die = false;
  resumed = false;
  ASSERT_DEATH(try_and_die(target, true), "");
  std::cout << "Fetcher died, retrying" << std::endl;
  resume(target);
}

TEST(FetcherDeathTest, TestResumeAfterSigkill) {
  TemporaryDirectory temp_dir;
  config.storage.path = temp_dir.Path();

  Json::Value target_json;
  target_json["hashes"]["sha256"] = "dd7bd1c37a3226e520b8d6939c30991b1c08772d5dab62b381c3a63541dc629a";
  target_json["length"] = 100 * (1 << 20);

  Uptane::Target target("large_file", target_json);
  die = false;
  resumed = false;
  ASSERT_DEATH(try_and_die(target, false), "");
  std::cout << "Fetcher died, retrying" << std::endl;
  resume(target);
}

#ifndef __NO_MAIN__
int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);

  logger_init();
  logger_set_threshold(boost::log::trivial::trace);

  std::string port = TestUtils::getFreePort();
  server = "http://127.0.0.1:" + port;
  config.uptane.repo_server = server;
  boost::process::child http_server_process("tests/fake_http_server/fake_test_server.py", port, "-f");
  TestUtils::waitForServer(server + "/");
  return RUN_ALL_TESTS();
}
#endif  // __NO_MAIN__
<|endoftext|>


<commit_before>#include <iostream>
#include <unistd.h>

#include "pluginstatemanager.h"

PluginStateManager::PluginStateManager(LoggingFunctionCB logger)
  : _enqueueCallback(NULL),
    _logger(logger),
    _pluginThread(NULL)
{
}

PluginStateManager::~PluginStateManager(void)
{
}

void PluginStateManager::runTestEventLoop(void)
{
    std::cout << "generating 9 events in a sleep loop" << std::endl;
    for (size_t i = 0; i < 9; i++) {
        sleep(1);
        _enqueueCallback(this, (void *)"echo", _callbackArg);
    }
    std::cout << "done" << std::endl;
}

//! just queue up a copy of the device settings for use in preflightComplete
int PluginStateManager::configPassthrough(libconfig::Config *pluginConfiguration)
{
    _config = pluginConfiguration;
    return 0;
}

int PluginStateManager::preflightComplete(void)
{
    return 0;
}

int PluginStateManager::deliverValue(GenericTLV *value)
{
    return 0;
}

void PluginStateManager::commenceEventing(EnqueueEventHandler enqueueCallback, void *arg)
{
    _logger(LOG_INFO, "  - commence eventing");
    _enqueueCallback = enqueueCallback;
    _callbackArg = arg;
    //_testEventThread = std::thread(std::bind(&PluginStateManager::runTestEventLoop, this));
}

void PluginStateManager::ceaseEventing(void)
{
    _logger(LOG_INFO, "  - Cease eventing");
}
<commit_msg>clean up test code thats not needed<commit_after>#include <iostream>
#include <unistd.h>

#include "pluginstatemanager.h"

PluginStateManager::PluginStateManager(LoggingFunctionCB logger)
    : _enqueueCallback(NULL)
    , _logger(logger)
    , _pluginThread(NULL)
{
}

PluginStateManager::~PluginStateManager(void) {}

//! just queue up a copy of the device settings for use in preflightComplete
int PluginStateManager::configPassthrough(libconfig::Config *pluginConfiguration)
{
    _config = pluginConfiguration;

    return 0;
}

int PluginStateManager::preflightComplete(void)
{
    return 0;
}

int PluginStateManager::deliverValue(GenericTLV *value)
{
    return 0;
}

void PluginStateManager::commenceEventing(EnqueueEventHandler enqueueCallback, void *arg)
{
    _logger(LOG_INFO, "  - commence eventing");
    _enqueueCallback = enqueueCallback;
    _callbackArg = arg;
    //_testEventThread = std::thread(std::bind(&PluginStateManager::runTestEventLoop, this));
}

void PluginStateManager::ceaseEventing(void)
{
    _logger(LOG_INFO, "  - Cease eventing");
}
<|endoftext|>


<commit_before>// 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

#ifndef __PROCESS_LOGGING_HPP__
#define __PROCESS_LOGGING_HPP__

#include <glog/logging.h>

#include <process/future.hpp>
#include <process/http.hpp>
#include <process/process.hpp>
#include <process/timeout.hpp>

namespace process {

class Logging : public Process<Logging>
{
public:
  Logging()
    : ProcessBase("logging"),
      original(FLAGS_v)
  {
    // Make sure all reads/writes can be done atomically (i.e., to
    // make sure VLOG(*) statements don't read partial writes).
    // TODO(benh): Use "atomics" primitives for doing reads/writes of
    // FLAGS_v anyway to account for proper memory barriers.
    CHECK(sizeof(FLAGS_v) == sizeof(int32_t));
  }

  virtual ~Logging() {}

protected:
  virtual void initialize()
  {
    route("/toggle", TOGGLE_HELP(), &This::toggle);
  }

private:
  Future<http::Response> toggle(const http::Request& request);

  void set(int v)
  {
    if (FLAGS_v != v) {
      VLOG(FLAGS_v) << "Setting verbose logging level to " << v;
      FLAGS_v = v;
      __sync_synchronize(); // Ensure 'FLAGS_v' visible in other threads.
    }
  }

  void revert()
  {
    if (timeout.remaining() == Seconds(0)) {
      set(original);
    }
  }

  static const std::string TOGGLE_HELP();

  Timeout timeout;

  const int32_t original; // Original value of FLAGS_v.
};

} // namespace process {

#endif // __PROCESS_LOGGING_HPP__
<commit_msg>Used Windows-compatible memory fence in libprocess logging.<commit_after>// 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

#ifndef __PROCESS_LOGGING_HPP__
#define __PROCESS_LOGGING_HPP__

#include <glog/logging.h>

#include <process/future.hpp>
#include <process/http.hpp>
#include <process/process.hpp>
#include <process/timeout.hpp>

namespace process {

class Logging : public Process<Logging>
{
public:
  Logging()
    : ProcessBase("logging"),
      original(FLAGS_v)
  {
    // Make sure all reads/writes can be done atomically (i.e., to
    // make sure VLOG(*) statements don't read partial writes).
    // TODO(benh): Use "atomics" primitives for doing reads/writes of
    // FLAGS_v anyway to account for proper memory barriers.
    CHECK(sizeof(FLAGS_v) == sizeof(int32_t));
  }

  virtual ~Logging() {}

protected:
  virtual void initialize()
  {
    route("/toggle", TOGGLE_HELP(), &This::toggle);
  }

private:
  Future<http::Response> toggle(const http::Request& request);

  void set(int v)
  {
    if (FLAGS_v != v) {
      VLOG(FLAGS_v) << "Setting verbose logging level to " << v;
      FLAGS_v = v;

      // Ensure 'FLAGS_v' visible in other threads.
#ifdef __WINDOWS__
      MemoryBarrier();
#else
      __sync_synchronize();
#endif // __WINDOWS__
    }
  }

  void revert()
  {
    if (timeout.remaining() == Seconds(0)) {
      set(original);
    }
  }

  static const std::string TOGGLE_HELP();

  Timeout timeout;

  const int32_t original; // Original value of FLAGS_v.
};

} // namespace process {

#endif // __PROCESS_LOGGING_HPP__
<|endoftext|>