<commit_before>/*
 * Copyright (c) 2007 Digital Bazaar, Inc.  All rights reserved.
 */
#include "RateAverager.h"
#include "System.h"
#include "Math.h"

using namespace db::rt;
using namespace db::util;

RateAverager::RateAverager(unsigned long long windowLength)
{
   reset();

   // set window lengths
   mCurrentWindow.setLength(windowLength);
   mNextWindow.setLength(windowLength);
}

RateAverager::~RateAverager()
{
}

void RateAverager::reset()
{
   // reset start and stop times
   setStartTime(0);
   setStopTime(0);

   // reset time passed
   mTimePassed = 0;

   // reset last time a rate was added
   mLastAddTime = System::getCurrentMilliseconds();

   // reset the windows
   mCurrentWindow.reset();
   mNextWindow.reset();

   // reset total item count
   mTotalItemCount = 0;
}

void RateAverager::setStartTime(unsigned long long time)
{
   mStartTime = time;
}

void RateAverager::setStopTime(unsigned long long time)
{
   mStopTime = time;
}

void RateAverager::setWindowStartTimes(unsigned long long time)
{
   // set current window start time
   mCurrentWindow.setStartTime(time);

   // set next window start time
   mNextWindow.setStartTime(time + getHalfWindowLength());
}

unsigned long long RateAverager::getHalfWindowLength()
{
   return (unsigned long long)Math::round(getWindowLength() / 2.0);
}

void RateAverager::updateWindowLengths(unsigned long long length)
{
   // set the current window length, adjusting items
   mCurrentWindow.setLength(length, true);

   // set the next window length, adjusting items
   mNextWindow.setLength(length, true);

   // update the next window start time
   mNextWindow.setStartTime(
      mCurrentWindow.getStartTime() + getHalfWindowLength());
}

void RateAverager::moveCurrentWindow()
{
   // set the current window to the next window
   mCurrentWindow.setEqualTo(mNextWindow);

   // reset the next window
   mNextWindow.reset();

   // set the next window start time
   mNextWindow.setStartTime(
      mCurrentWindow.getStartTime() + getHalfWindowLength());
}

void RateAverager::start(unsigned long long time)
{
   lock();
   {
      if(!isRunning())
      {
         // reset
         reset();

         // now running
         mRunning = true;

         // set start time
         setStartTime(time);

         // set window start times
         setWindowStartTimes(time);
      }
   }
   unlock();
}

void RateAverager::stop(unsigned long long time)
{
   lock();
   {
      if(isRunning())
      {
         // no longer running
         mRunning = false;

         // set stop time
         setStopTime(time);
      }
   }
   unlock();
}

void RateAverager::restart()
{
   lock();
   {
      restart(getCurrentTime(), 0);
   }
   unlock();
}

void RateAverager::restart(
   unsigned long long stopTime, unsigned long long startTime)
{
   lock();
   {
      stop(stopTime);
      start(startTime);
   }
   unlock();
}

bool RateAverager::isRunning()
{
   bool rval = false;

   lock();
   {
      rval = mRunning;
   }
   unlock();

   return rval;
}

void RateAverager::addRate(unsigned long long count)
{
   lock();
   {
      addRate(count, System::getCurrentMilliseconds() - mLastAddTime);
   }
   unlock();
}

void RateAverager::addRate(
   unsigned long long count, unsigned long long interval)
{
   lock();
   {
      // increase the time passed
      mTimePassed = Math::maximum(0, mTimePassed + interval);

      // get the remaining time in the current window
      unsigned long long remaining = mCurrentWindow.getRemainingTime();

      // see if the interval can be added to the current window without
      // overflowing
      if(interval < remaining)
      {
         // get the overlap time between the current window and the next window
         unsigned long long overlap =
            mCurrentWindow.getCurrentTime() + interval -
            mNextWindow.getCurrentTime();

         if(overlap > 0)
         {
            // get the portion of the item count in the overlap
            double rate = TimeWindow::getItemsPerMillisecond(count, interval);
            unsigned long long portion =
               (unsigned long long)Math::round(rate * overlap);

            // increase the next window count and time
            mNextWindow.increaseItemCount(portion, overlap);
         }

         // add the count and interval to the current window
         mCurrentWindow.increaseItemCount(count, interval);
      }
      else
      {
         // there is overflow, so we'll be moving windows

         // get the overflow of the interval that cannot be added to
         // the current window
         unsigned long long overflow = interval - remaining;

         // add the amount of time it takes to get the next window up to
         // the end of the current window
         overflow += mCurrentWindow.getEndTime() - mNextWindow.getCurrentTime();

         // get the remaining time in the next window
         remaining = mNextWindow.getRemainingTime();

         // see if the overflow can be added to the next window
         if(overflow < remaining)
         {
            // get the portion of the item count in the overflow
            double rate = TimeWindow::getItemsPerMillisecond(count, interval);
            unsigned long long portion =
               (unsigned long long)Math::round(rate * overflow);

            // increase the next window count and time
            mNextWindow.increaseItemCount(portion, overflow);

            // move the current window
            moveCurrentWindow();
         }
         else
         {
            // reset the windows
            mCurrentWindow.reset();
            mNextWindow.reset();

            // set the current window start time to half of a window - 1
            // before the the current time
            unsigned long long startTime =
               getCurrentTime() - getHalfWindowLength() - 1;
            setWindowStartTimes(startTime);

            // get the remainder of the interval that will be used
            unsigned long long remainder =
               getCurrentTime() - mCurrentWindow.getStartTime();

            // add the portion of the item count to the current window
            double rate = TimeWindow::getItemsPerMillisecond(count, interval);
            unsigned long long portion =
               (unsigned long long)Math::round(rate * remainder);
            mCurrentWindow.increaseItemCount(portion, remainder);
         }
      }

      // add items to the total item count
      mTotalItemCount = Math::maximum(0, mTotalItemCount + count);

      // update the last rate add time
      mLastAddTime = System::getCurrentMilliseconds();
   }
   unlock();
}

unsigned long long RateAverager::getStartTime()
{
   return mStartTime;
}

unsigned long long RateAverager::getStopTime()
{
   return mStopTime;
}

unsigned long long RateAverager::getCurrentTime()
{
   unsigned long long rval = 0;

   lock();
   {
      rval = getStartTime() + getTimePassed();
   }
   unlock();

   return rval;
}

unsigned long long RateAverager::getTimePassed()
{
   unsigned long long rval = 0;

   lock();
   {
      if(isRunning())
      {
         rval = mTimePassed;
      }
      else
      {
         rval = getStopTime() - getStartTime();
      }
   }
   unlock();

   return rval;
}

double RateAverager::getCurrentRate()
{
   double rval = 0.0;

   lock();
   {
      // make sure that the current time is greater than 0
      if(getCurrentTime() > 0)
      {
         // get the current window rate
         rval = mCurrentWindow.getIncreaseRate();
      }
   }
   unlock();

   return rval;
}

double RateAverager::getTotalRate()
{
   double rval = 0.0;

   lock();
   {
      // make sure that the current time is greater than 0
      if(getCurrentTime() > 0)
      {
         // get the rate in items per second
         rval = TimeWindow::getItemsPerSecond(mTotalItemCount, getTimePassed());
      }
   }
   unlock();

   return rval;
}

unsigned long long RateAverager::getTotalItemCount()
{
   return mTotalItemCount;
}

void RateAverager::setWindowLength(unsigned long long length)
{
   lock();
   {
      // the window length must be at least two because two windows that
      // are 1/2 of the window length apart are always stored -- and
      // this RateAverager is only accurate to 1 whole millisecond
      length = Math::maximum(2, length);

      // update window lengths
      updateWindowLengths(length);
   }
   unlock();
}

unsigned long long RateAverager::getWindowLength()
{
   return mCurrentWindow.getLength();
}

unsigned long long RateAverager::getETA(unsigned long long count)
{
   unsigned long long rval = 0;

   lock();
   {
      if(count > 0)
      {
         // multiply the current rate by the count
         rval = (unsigned long long)Math::round(count / getCurrentRate());
      }
   }
   unlock();

   return rval;
}
<commit_msg>Added missing implementation for RateAverager::stop().<commit_after>/*
 * Copyright (c) 2007 Digital Bazaar, Inc.  All rights reserved.
 */
#include "RateAverager.h"
#include "System.h"
#include "Math.h"

using namespace db::rt;
using namespace db::util;

RateAverager::RateAverager(unsigned long long windowLength)
{
   reset();

   // set window lengths
   mCurrentWindow.setLength(windowLength);
   mNextWindow.setLength(windowLength);
}

RateAverager::~RateAverager()
{
}

void RateAverager::reset()
{
   // reset start and stop times
   setStartTime(0);
   setStopTime(0);

   // reset time passed
   mTimePassed = 0;

   // reset last time a rate was added
   mLastAddTime = System::getCurrentMilliseconds();

   // reset the windows
   mCurrentWindow.reset();
   mNextWindow.reset();

   // reset total item count
   mTotalItemCount = 0;
}

void RateAverager::setStartTime(unsigned long long time)
{
   mStartTime = time;
}

void RateAverager::setStopTime(unsigned long long time)
{
   mStopTime = time;
}

void RateAverager::setWindowStartTimes(unsigned long long time)
{
   // set current window start time
   mCurrentWindow.setStartTime(time);

   // set next window start time
   mNextWindow.setStartTime(time + getHalfWindowLength());
}

unsigned long long RateAverager::getHalfWindowLength()
{
   return (unsigned long long)Math::round(getWindowLength() / 2.0);
}

void RateAverager::updateWindowLengths(unsigned long long length)
{
   // set the current window length, adjusting items
   mCurrentWindow.setLength(length, true);

   // set the next window length, adjusting items
   mNextWindow.setLength(length, true);

   // update the next window start time
   mNextWindow.setStartTime(
      mCurrentWindow.getStartTime() + getHalfWindowLength());
}

void RateAverager::moveCurrentWindow()
{
   // set the current window to the next window
   mCurrentWindow.setEqualTo(mNextWindow);

   // reset the next window
   mNextWindow.reset();

   // set the next window start time
   mNextWindow.setStartTime(
      mCurrentWindow.getStartTime() + getHalfWindowLength());
}

void RateAverager::start(unsigned long long time)
{
   lock();
   {
      if(!isRunning())
      {
         // reset
         reset();

         // now running
         mRunning = true;

         // set start time
         setStartTime(time);

         // set window start times
         setWindowStartTimes(time);
      }
   }
   unlock();
}

void RateAverager::stop()
{
   lock();
   {
      stop(getCurrentTime());
   }
   unlock();
}

void RateAverager::stop(unsigned long long time)
{
   lock();
   {
      if(isRunning())
      {
         // no longer running
         mRunning = false;

         // set stop time
         setStopTime(time);
      }
   }
   unlock();
}

void RateAverager::restart()
{
   lock();
   {
      restart(getCurrentTime(), 0);
   }
   unlock();
}

void RateAverager::restart(
   unsigned long long stopTime, unsigned long long startTime)
{
   lock();
   {
      stop(stopTime);
      start(startTime);
   }
   unlock();
}

bool RateAverager::isRunning()
{
   bool rval = false;

   lock();
   {
      rval = mRunning;
   }
   unlock();

   return rval;
}

void RateAverager::addRate(unsigned long long count)
{
   lock();
   {
      addRate(count, System::getCurrentMilliseconds() - mLastAddTime);
   }
   unlock();
}

void RateAverager::addRate(
   unsigned long long count, unsigned long long interval)
{
   lock();
   {
      // increase the time passed
      mTimePassed = Math::maximum(0, mTimePassed + interval);

      // get the remaining time in the current window
      unsigned long long remaining = mCurrentWindow.getRemainingTime();

      // see if the interval can be added to the current window without
      // overflowing
      if(interval < remaining)
      {
         // get the overlap time between the current window and the next window
         unsigned long long overlap =
            mCurrentWindow.getCurrentTime() + interval -
            mNextWindow.getCurrentTime();

         if(overlap > 0)
         {
            // get the portion of the item count in the overlap
            double rate = TimeWindow::getItemsPerMillisecond(count, interval);
            unsigned long long portion =
               (unsigned long long)Math::round(rate * overlap);

            // increase the next window count and time
            mNextWindow.increaseItemCount(portion, overlap);
         }

         // add the count and interval to the current window
         mCurrentWindow.increaseItemCount(count, interval);
      }
      else
      {
         // there is overflow, so we'll be moving windows

         // get the overflow of the interval that cannot be added to
         // the current window
         unsigned long long overflow = interval - remaining;

         // add the amount of time it takes to get the next window up to
         // the end of the current window
         overflow += mCurrentWindow.getEndTime() - mNextWindow.getCurrentTime();

         // get the remaining time in the next window
         remaining = mNextWindow.getRemainingTime();

         // see if the overflow can be added to the next window
         if(overflow < remaining)
         {
            // get the portion of the item count in the overflow
            double rate = TimeWindow::getItemsPerMillisecond(count, interval);
            unsigned long long portion =
               (unsigned long long)Math::round(rate * overflow);

            // increase the next window count and time
            mNextWindow.increaseItemCount(portion, overflow);

            // move the current window
            moveCurrentWindow();
         }
         else
         {
            // reset the windows
            mCurrentWindow.reset();
            mNextWindow.reset();

            // set the current window start time to half of a window - 1
            // before the the current time
            unsigned long long startTime =
               getCurrentTime() - getHalfWindowLength() - 1;
            setWindowStartTimes(startTime);

            // get the remainder of the interval that will be used
            unsigned long long remainder =
               getCurrentTime() - mCurrentWindow.getStartTime();

            // add the portion of the item count to the current window
            double rate = TimeWindow::getItemsPerMillisecond(count, interval);
            unsigned long long portion =
               (unsigned long long)Math::round(rate * remainder);
            mCurrentWindow.increaseItemCount(portion, remainder);
         }
      }

      // add items to the total item count
      mTotalItemCount = Math::maximum(0, mTotalItemCount + count);

      // update the last rate add time
      mLastAddTime = System::getCurrentMilliseconds();
   }
   unlock();
}

unsigned long long RateAverager::getStartTime()
{
   return mStartTime;
}

unsigned long long RateAverager::getStopTime()
{
   return mStopTime;
}

unsigned long long RateAverager::getCurrentTime()
{
   unsigned long long rval = 0;

   lock();
   {
      rval = getStartTime() + getTimePassed();
   }
   unlock();

   return rval;
}

unsigned long long RateAverager::getTimePassed()
{
   unsigned long long rval = 0;

   lock();
   {
      if(isRunning())
      {
         rval = mTimePassed;
      }
      else
      {
         rval = getStopTime() - getStartTime();
      }
   }
   unlock();

   return rval;
}

double RateAverager::getCurrentRate()
{
   double rval = 0.0;

   lock();
   {
      // make sure that the current time is greater than 0
      if(getCurrentTime() > 0)
      {
         // get the current window rate
         rval = mCurrentWindow.getIncreaseRate();
      }
   }
   unlock();

   return rval;
}

double RateAverager::getTotalRate()
{
   double rval = 0.0;

   lock();
   {
      // make sure that the current time is greater than 0
      if(getCurrentTime() > 0)
      {
         // get the rate in items per second
         rval = TimeWindow::getItemsPerSecond(mTotalItemCount, getTimePassed());
      }
   }
   unlock();

   return rval;
}

unsigned long long RateAverager::getTotalItemCount()
{
   return mTotalItemCount;
}

void RateAverager::setWindowLength(unsigned long long length)
{
   lock();
   {
      // the window length must be at least two because two windows that
      // are 1/2 of the window length apart are always stored -- and
      // this RateAverager is only accurate to 1 whole millisecond
      length = Math::maximum(2, length);

      // update window lengths
      updateWindowLengths(length);
   }
   unlock();
}

unsigned long long RateAverager::getWindowLength()
{
   return mCurrentWindow.getLength();
}

unsigned long long RateAverager::getETA(unsigned long long count)
{
   unsigned long long rval = 0;

   lock();
   {
      if(count > 0)
      {
         // multiply the current rate by the count
         rval = (unsigned long long)Math::round(count / getCurrentRate());
      }
   }
   unlock();

   return rval;
}
<|endoftext|>


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

#include "souper/Tool/CandidateMapUtils.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "souper/KVStore/KVStore.h"
#include "souper/SMTLIB2/Solver.h"

using namespace llvm;

void souper::AddToCandidateMap(CandidateMap &M,
                               const CandidateReplacement &CR) {
  M.emplace_back(CR);
}

void souper::AddModuleToCandidateMap(InstContext &IC, ExprBuilderContext &EBC,
                                     CandidateMap &CandMap, llvm::Module *M) {
  for (auto &F : *M) {
    FunctionCandidateSet CS = ExtractCandidates(&F, IC, EBC);
    for (auto &B : CS.Blocks) {
      for (auto &R : B->Replacements) {
        AddToCandidateMap(CandMap, R);
      }
    }
  }
}

namespace souper {

bool SolveCandidateMap(llvm::raw_ostream &OS, CandidateMap &M,
                       Solver *S, InstContext &IC, KVStore *KVForStaticProfile) {
  if (S) {
    OS << "; Listing valid replacements.\n";
    OS << "; Using solver: " << S->getName() << '\n';

    std::vector<int> Profile;
    std::map<std::string,int> Index;
    for (int I=0; I < M.size(); ++I) {
      auto &Cand = M[I];
      ReplacementContext Context;
      auto S = GetReplacementLHSString(Cand.BPCs, Cand.PCs,
                                       Cand.Mapping.LHS, Context);
      if (Index.find(S) == Index.end()) {
        Index[S] = I;
        Profile.push_back(1);
      } else {
        ++Profile[Index[S]];
        Profile.push_back(0);
      }
    }

    for (int I=0; I < M.size(); ++I) {
      if (Profile[I] == 0)
        continue;
      auto &Cand = M[I];

      if (KVForStaticProfile) {
        std::string Str;
        llvm::raw_string_ostream Loc(Str);
        Instruction *I = Cand.Origin;
        I->getDebugLoc().print(Loc);
        std::string HField = "sprofile " + Loc.str();
        ReplacementContext Context;
        KVForStaticProfile->hIncrBy(GetReplacementLHSString(Cand.BPCs,
            Cand.PCs, Cand.Mapping.LHS, Context), HField, 1);
      }

      Inst *RHS;
      if (std::error_code EC =
              S->infer(Cand.BPCs, Cand.PCs, Cand.Mapping.LHS, RHS, IC)) {
        llvm::errs() << "Unable to query solver: " << EC.message() << '\n';
        return false;
      }
      if (RHS) {
        OS << '\n';
        OS << "; Static profile " << Profile[I] << '\n';
        Cand.Mapping.RHS = RHS;
        Cand.printFunction(OS);
        Cand.print(OS);
      }
    }
  } else {
    OS << "; No solver specified; listing all candidate replacements.\n";
    for (auto &Cand : M) {
      OS << '\n';
      Cand.printFunction(OS);
      ReplacementContext Context;
      Cand.printLHS(OS, Context);
    }
  }

  return true;
}

bool CheckCandidateMap(llvm::Module &Mod, CandidateMap &M, Solver *S,
                       InstContext &IC) {
  if (!S) {
    llvm::errs() << "Solver required in -check mode\n";
    return false;
  }

  unsigned ExpectedID = Mod.getContext().getMDKindID("expected");

  bool OK = true;
  for (auto &Cand : M) {
    Inst *RHS;
    if (std::error_code EC =
            S->infer(Cand.BPCs, Cand.PCs, Cand.Mapping.LHS, RHS, IC)) {
      llvm::errs() << "Unable to query solver: " << EC.message() << '\n';
      return false;
    }
    if (RHS) {
      Cand.Mapping.RHS = RHS;
      if (Cand.Mapping.RHS->K != Inst::Const) {
        llvm::errs() << "found replacement:\n";
        Cand.printFunction(llvm::errs());
        Cand.print(llvm::errs());
        llvm::errs() << "but cannot yet analyze non-constant replacements\n";
        OK = false;
        continue;
      }
      llvm::APInt ActualVal = Cand.Mapping.RHS->Val;

      llvm::Instruction *Inst = Cand.Origin;
      llvm::MDNode *ExpectedMD = Inst->getMetadata(ExpectedID);
      if (!ExpectedMD) {
        llvm::errs() << "instruction:\n";
        Inst->print(llvm::errs(), /*IsForDebug=*/true);
        llvm::errs() << "\n";
        llvm::errs() << "unexpected simplification:\n";
        Cand.printFunction(llvm::errs());
        Cand.print(llvm::errs());
        OK = false;
        continue;
      }

      if (ExpectedMD->getNumOperands() != 1 ||
          !mdconst::hasa<ConstantInt>(ExpectedMD->getOperand(0))) {
        llvm::errs() << "instruction:\n";
        Inst->print(llvm::errs(), /*IsForDebug=*/true);
        llvm::errs() << "\n";
        llvm::errs() << "invalid metadata\n";
        OK = false;
        continue;
      }
      llvm::APInt ExpectedVal =
        mdconst::extract<ConstantInt>(ExpectedMD->getOperand(0))->getValue();
      Inst->setMetadata(ExpectedID, 0);
      if (ExpectedVal.getBitWidth() != ActualVal.getBitWidth()) {
        llvm::errs() << "metadata width doesn't match value width\n";
        OK = false;
        continue;
      }
      if (ExpectedVal != ActualVal) {
        llvm::errs() << "instruction:\n";
        Inst->print(llvm::errs(), /*IsForDebug=*/true);
        llvm::errs() << "\n";
        llvm::errs() << "unexpected simplification, wanted " << ExpectedVal
                     << ":\n";
        Cand.printFunction(llvm::errs());
        Cand.print(llvm::errs());
        OK = false;
        continue;
      }
    }
  }

  for (const auto &F : Mod) {
    for (const auto &BB : F) {
      for (const auto &Inst : BB) {
        llvm::MDNode *ExpectedMD = Inst.getMetadata(ExpectedID);
        if (ExpectedMD) {
          llvm::errs() << "instruction:\n";
          Inst.print(llvm::errs(), /*IsForDebug=*/true);
          llvm::errs() << "\n";
          llvm::errs() << "expected simplification, none found\n";
          OK = false;
          continue;
        }
      }
    }
  }

  return OK;
}

}
<commit_msg>ugh!! it has been forever since I touched this code but it looks like (#384)<commit_after>// Copyright 2014 The Souper Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "souper/Tool/CandidateMapUtils.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "souper/KVStore/KVStore.h"
#include "souper/SMTLIB2/Solver.h"

using namespace llvm;

void souper::AddToCandidateMap(CandidateMap &M,
                               const CandidateReplacement &CR) {
  M.emplace_back(CR);
}

void souper::AddModuleToCandidateMap(InstContext &IC, ExprBuilderContext &EBC,
                                     CandidateMap &CandMap, llvm::Module *M) {
  for (auto &F : *M) {
    FunctionCandidateSet CS = ExtractCandidates(&F, IC, EBC);
    for (auto &B : CS.Blocks) {
      for (auto &R : B->Replacements) {
        AddToCandidateMap(CandMap, R);
      }
    }
  }
}

namespace souper {

bool SolveCandidateMap(llvm::raw_ostream &OS, CandidateMap &M,
                       Solver *S, InstContext &IC, KVStore *KVForStaticProfile) {
  if (S) {
    OS << "; Listing valid replacements.\n";
    OS << "; Using solver: " << S->getName() << '\n';

    std::vector<int> Profile;
    std::map<std::string,int> Index;
    for (int I=0; I < M.size(); ++I) {
      auto &Cand = M[I];
      ReplacementContext Context;
      auto S = GetReplacementLHSString(Cand.BPCs, Cand.PCs,
                                       Cand.Mapping.LHS, Context);
      if (Index.find(S) == Index.end()) {
        Index[S] = I;
        Profile.push_back(1);
      } else {
        ++Profile[Index[S]];
        Profile.push_back(0);
      }
    }

    for (int I=0; I < M.size(); ++I) {
      if (Profile[I] == 0)
        continue;
      auto &Cand = M[I];

      if (KVForStaticProfile) {
        std::string Str;
        llvm::raw_string_ostream Loc(Str);
        Instruction *I = Cand.Origin;
        I->getDebugLoc().print(Loc);
        std::string HField = "sprofile " + Loc.str();
        ReplacementContext Context;
        KVForStaticProfile->hIncrBy(GetReplacementLHSString(Cand.BPCs,
            Cand.PCs, Cand.Mapping.LHS, Context), HField, 1);
      }

      Inst *RHS = 0;
      if (std::error_code EC =
              S->infer(Cand.BPCs, Cand.PCs, Cand.Mapping.LHS, RHS, IC)) {
        llvm::errs() << "Unable to query solver: " << EC.message() << '\n';
        return false;
      }
      if (RHS) {
        OS << '\n';
        OS << "; Static profile " << Profile[I] << '\n';
        Cand.Mapping.RHS = RHS;
        Cand.printFunction(OS);
        Cand.print(OS);
      }
    }
  } else {
    OS << "; No solver specified; listing all candidate replacements.\n";
    for (auto &Cand : M) {
      OS << '\n';
      Cand.printFunction(OS);
      ReplacementContext Context;
      Cand.printLHS(OS, Context);
    }
  }

  return true;
}

bool CheckCandidateMap(llvm::Module &Mod, CandidateMap &M, Solver *S,
                       InstContext &IC) {
  if (!S) {
    llvm::errs() << "Solver required in -check mode\n";
    return false;
  }

  unsigned ExpectedID = Mod.getContext().getMDKindID("expected");

  bool OK = true;
  for (auto &Cand : M) {
    Inst *RHS = 0;
    if (std::error_code EC =
            S->infer(Cand.BPCs, Cand.PCs, Cand.Mapping.LHS, RHS, IC)) {
      llvm::errs() << "Unable to query solver: " << EC.message() << '\n';
      return false;
    }
    if (RHS) {
      Cand.Mapping.RHS = RHS;
      if (Cand.Mapping.RHS->K != Inst::Const) {
        llvm::errs() << "found replacement:\n";
        Cand.printFunction(llvm::errs());
        Cand.print(llvm::errs());
        llvm::errs() << "but cannot yet analyze non-constant replacements\n";
        OK = false;
        continue;
      }
      llvm::APInt ActualVal = Cand.Mapping.RHS->Val;

      llvm::Instruction *Inst = Cand.Origin;
      llvm::MDNode *ExpectedMD = Inst->getMetadata(ExpectedID);
      if (!ExpectedMD) {
        llvm::errs() << "instruction:\n";
        Inst->print(llvm::errs(), /*IsForDebug=*/true);
        llvm::errs() << "\n";
        llvm::errs() << "unexpected simplification:\n";
        Cand.printFunction(llvm::errs());
        Cand.print(llvm::errs());
        OK = false;
        continue;
      }

      if (ExpectedMD->getNumOperands() != 1 ||
          !mdconst::hasa<ConstantInt>(ExpectedMD->getOperand(0))) {
        llvm::errs() << "instruction:\n";
        Inst->print(llvm::errs(), /*IsForDebug=*/true);
        llvm::errs() << "\n";
        llvm::errs() << "invalid metadata\n";
        OK = false;
        continue;
      }
      llvm::APInt ExpectedVal =
        mdconst::extract<ConstantInt>(ExpectedMD->getOperand(0))->getValue();
      Inst->setMetadata(ExpectedID, 0);
      if (ExpectedVal.getBitWidth() != ActualVal.getBitWidth()) {
        llvm::errs() << "metadata width doesn't match value width\n";
        OK = false;
        continue;
      }
      if (ExpectedVal != ActualVal) {
        llvm::errs() << "instruction:\n";
        Inst->print(llvm::errs(), /*IsForDebug=*/true);
        llvm::errs() << "\n";
        llvm::errs() << "unexpected simplification, wanted " << ExpectedVal
                     << ":\n";
        Cand.printFunction(llvm::errs());
        Cand.print(llvm::errs());
        OK = false;
        continue;
      }
    }
  }

  for (const auto &F : Mod) {
    for (const auto &BB : F) {
      for (const auto &Inst : BB) {
        llvm::MDNode *ExpectedMD = Inst.getMetadata(ExpectedID);
        if (ExpectedMD) {
          llvm::errs() << "instruction:\n";
          Inst.print(llvm::errs(), /*IsForDebug=*/true);
          llvm::errs() << "\n";
          llvm::errs() << "expected simplification, none found\n";
          OK = false;
          continue;
        }
      }
    }
  }

  return OK;
}

}
<|endoftext|>


<commit_before>#ifndef CLIENT_WSS_HPP
#define	CLIENT_WSS_HPP

#include "client_ws.hpp"
#include <boost/asio/ssl.hpp>

namespace SimpleWeb {
    typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> WSS;

    template<>
    class SocketClient<WSS> : public SocketClientBase<WSS> {
    public:
        SocketClient(const std::string& server_port_path, bool verify_certificate=true) : SocketClientBase<WSS>::SocketClientBase(server_port_path, 443),
                asio_context(boost::asio::ssl::context::sslv23) {
            if(verify_certificate)
                asio_context.set_verify_mode(boost::asio::ssl::verify_peer);
            else
                asio_context.set_verify_mode(boost::asio::ssl::verify_none);
        };

        SocketClient(const std::string& server_port_path, const std::string& verify_file) : SocketClientBase<WSS>::SocketClientBase(server_port_path, 443),
                asio_context(boost::asio::ssl::context::sslv23) {
                asio_context.set_verify_mode(boost::asio::ssl::verify_peer);
                asio_context.load_verify_file(verify_file);
        };

    private:
        boost::asio::ssl::context asio_context;

        void connect() {
            boost::asio::ip::tcp::resolver::query query(host, std::to_string(port));

            asio_resolver.async_resolve(query, [this]
                    (const boost::system::error_code &ec, boost::asio::ip::tcp::resolver::iterator it){
                if(!ec) {
                    connection=std::unique_ptr<Connection>(new Connection(new WSS(asio_io_service, asio_context)));

                    boost::asio::async_connect(connection->socket->lowest_layer(), it, [this]
                            (const boost::system::error_code &ec, boost::asio::ip::tcp::resolver::iterator it){
                        if(!ec) {
                            connection->socket->async_handshake(boost::asio::ssl::stream_base::client,
                                    [this](const boost::system::error_code& ec) {
                                if(!ec)
                                    handshake();
                                else
                                    throw std::invalid_argument(ec.message());
                            });
                        }
                        else
                            throw std::invalid_argument(ec.message());
                    });
                }
                else
                    throw std::invalid_argument(ec.message());
            });
        }
    };
}

#endif	/* CLIENT_WSS_HPP */<commit_msg>Added possibility to use client certificate and trusted certification authority file<commit_after>#ifndef CLIENT_WSS_HPP
#define	CLIENT_WSS_HPP

#include "client_ws.hpp"
#include <boost/asio/ssl.hpp>

namespace SimpleWeb {
    typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> WSS;

    template<>
    class SocketClient<WSS> : public SocketClientBase<WSS> {
    public:
        SocketClient(const std::string& server_port_path, bool verify_certificate=true, const std::string& verify_file="", const std::string& cert_file="", const std::string& private_key_file="") : SocketClientBase<WSS>::SocketClientBase(server_port_path, 443),
                asio_context(boost::asio::ssl::context::sslv23) {
            if(verify_certificate)
                asio_context.set_verify_mode(boost::asio::ssl::verify_peer);
            else
                asio_context.set_verify_mode(boost::asio::ssl::verify_none);

            if(verify_file!="")
                asio_context.load_verify_file(verify_file);

            if(cert_file!="" && private_key_file!="") {
                asio_context.use_certificate_chain_file(cert_file);
                asio_context.use_private_key_file(private_key_file, boost::asio::ssl::context::pem);
            }
        };

    private:
        boost::asio::ssl::context asio_context;

        void connect() {
            boost::asio::ip::tcp::resolver::query query(host, std::to_string(port));

            asio_resolver.async_resolve(query, [this]
                    (const boost::system::error_code &ec, boost::asio::ip::tcp::resolver::iterator it){
                if(!ec) {
                    connection=std::unique_ptr<Connection>(new Connection(new WSS(asio_io_service, asio_context)));

                    boost::asio::async_connect(connection->socket->lowest_layer(), it, [this]
                            (const boost::system::error_code &ec, boost::asio::ip::tcp::resolver::iterator it){
                        if(!ec) {
                            connection->socket->async_handshake(boost::asio::ssl::stream_base::client,
                                    [this](const boost::system::error_code& ec) {
                                if(!ec)
                                    handshake();
                                else
                                    throw std::invalid_argument(ec.message());
                            });
                        }
                        else
                            throw std::invalid_argument(ec.message());
                    });
                }
                else
                    throw std::invalid_argument(ec.message());
            });
        }
    };
}

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


<commit_before>#include "cnn/devices.h"

#include <iostream>
#include <unsupported/Eigen/CXX11/Tensor>

#include "cnn/cuda.h"
#include "cnn/cnn.h"

using namespace std;

namespace cnn {

Device::~Device() {}

DeviceMemCheckpoint Device::mark(ComputationGraph *cg) {
  cg->incremental_forward(); // needed so that we actually allocate the needed memory
                             // for all existing nodes.
  DeviceMemCheckpoint cp;
  for(size_t i = 0; i < 3; ++i)
    cp.used[i] = pools[i]->used;
  return cp;
}

void Device::revert(DeviceMemCheckpoint cp) {
  for(size_t i = 0; i < 3; ++i) {
    assert(cp.used[i] <= pools[i]->used);
    pools[i]->used = cp.used[i];
  }
}

void Device::allocate_tensor(DeviceMempool mp, Tensor & tens) {
  assert(mp != DeviceMempool::NONE);
  assert(pools[(int)mp] != nullptr);
  tens.v = (float*)pools[(int)mp]->allocate(tens.d.size());
  tens.mem_pool = mp;
}

#if HAVE_CUDA
Device_GPU::Device_GPU(int my_id, int mb, int device_id) :
    Device(my_id, DeviceType::GPU, &gpu_mem), cuda_device_id(device_id), gpu_mem(device_id) {
  CUDA_CHECK(cudaSetDevice(device_id));
  CUBLAS_CHECK(cublasCreate(&cublas_handle));
  CUBLAS_CHECK(cublasSetPointerMode(cublas_handle, CUBLAS_POINTER_MODE_DEVICE));
  kSCALAR_MINUSONE = (float*)gpu_mem.malloc(sizeof(float));
  kSCALAR_ONE = (float*)gpu_mem.malloc(sizeof(float));
  kSCALAR_ZERO = (float*)gpu_mem.malloc(sizeof(float));
  float minusone = -1;
  CUDA_CHECK(cudaMemcpyAsync(kSCALAR_MINUSONE, &minusone, sizeof(float), cudaMemcpyHostToDevice));
  float one = 1;
  CUDA_CHECK(cudaMemcpyAsync(kSCALAR_ONE, &one, sizeof(float), cudaMemcpyHostToDevice));
  float zero = 0;
  CUDA_CHECK(cudaMemcpyAsync(kSCALAR_ZERO, &zero, sizeof(float), cudaMemcpyHostToDevice));

  // Initialize the Eigen device
  estream = new Eigen::CudaStreamDevice(device_id);
  edevice = new Eigen::GpuDevice(estream);

  // this is the big memory allocation. Do it in stages to make sure things are aligned.
  size_t byte_count = (size_t)((mb << 10)/3) << 10;
  for(size_t i = 0; i < 3; ++i)
    pools[i] = new AlignedMemoryPool(byte_count, mem);
}

Device_GPU::~Device_GPU() {}
#endif

// TODO we should be able to configure this carefully with a configuration
// script
// CPU -- 0 params
//     -- 50mb fxs
//     -- 50mb dEdfx
Device_CPU::Device_CPU(int my_id, int mb, bool shared) :
    Device(my_id, DeviceType::CPU, &cpu_mem), shmem(mem) {
  if (shared) shmem = new SharedAllocator();
  kSCALAR_MINUSONE = (float*) mem->malloc(sizeof(float));
  *kSCALAR_MINUSONE = -1;
  kSCALAR_ONE = (float*) mem->malloc(sizeof(float));
  *kSCALAR_ONE = 1;
  kSCALAR_ZERO = (float*) mem->malloc(sizeof(float));
  *kSCALAR_ZERO = 0;

  // Initialize the Eigen device
  edevice = new Eigen::DefaultDevice;

  // this is the big memory allocation. Do it in stages to make sure things are aligned.
  size_t byte_count = (size_t)((mb << 10)/3) << 10;
  for(size_t i = 0; i < 3; ++i)
    pools[i] = new AlignedMemoryPool(byte_count, mem);
}

Device_CPU::~Device_CPU() {}

} // namespace cnn
<commit_msg>Fixed bug forgetting to multiply by float size<commit_after>#include "cnn/devices.h"

#include <iostream>
#include <unsupported/Eigen/CXX11/Tensor>

#include "cnn/cuda.h"
#include "cnn/cnn.h"

using namespace std;

namespace cnn {

Device::~Device() {}

DeviceMemCheckpoint Device::mark(ComputationGraph *cg) {
  cg->incremental_forward(); // needed so that we actually allocate the needed memory
                             // for all existing nodes.
  DeviceMemCheckpoint cp;
  for(size_t i = 0; i < 3; ++i)
    cp.used[i] = pools[i]->used;
  return cp;
}

void Device::revert(DeviceMemCheckpoint cp) {
  for(size_t i = 0; i < 3; ++i) {
    assert(cp.used[i] <= pools[i]->used);
    pools[i]->used = cp.used[i];
  }
}

void Device::allocate_tensor(DeviceMempool mp, Tensor & tens) {
  assert(mp != DeviceMempool::NONE);
  assert(pools[(int)mp] != nullptr);
  tens.v = (float*)pools[(int)mp]->allocate(tens.d.size() * sizeof(float));
  tens.mem_pool = mp;
}

#if HAVE_CUDA
Device_GPU::Device_GPU(int my_id, int mb, int device_id) :
    Device(my_id, DeviceType::GPU, &gpu_mem), cuda_device_id(device_id), gpu_mem(device_id) {
  CUDA_CHECK(cudaSetDevice(device_id));
  CUBLAS_CHECK(cublasCreate(&cublas_handle));
  CUBLAS_CHECK(cublasSetPointerMode(cublas_handle, CUBLAS_POINTER_MODE_DEVICE));
  kSCALAR_MINUSONE = (float*)gpu_mem.malloc(sizeof(float));
  kSCALAR_ONE = (float*)gpu_mem.malloc(sizeof(float));
  kSCALAR_ZERO = (float*)gpu_mem.malloc(sizeof(float));
  float minusone = -1;
  CUDA_CHECK(cudaMemcpyAsync(kSCALAR_MINUSONE, &minusone, sizeof(float), cudaMemcpyHostToDevice));
  float one = 1;
  CUDA_CHECK(cudaMemcpyAsync(kSCALAR_ONE, &one, sizeof(float), cudaMemcpyHostToDevice));
  float zero = 0;
  CUDA_CHECK(cudaMemcpyAsync(kSCALAR_ZERO, &zero, sizeof(float), cudaMemcpyHostToDevice));

  // Initialize the Eigen device
  estream = new Eigen::CudaStreamDevice(device_id);
  edevice = new Eigen::GpuDevice(estream);

  // this is the big memory allocation. Do it in stages to make sure things are aligned.
  size_t byte_count = (size_t)((mb << 10)/3) << 10;
  for(size_t i = 0; i < 3; ++i)
    pools[i] = new AlignedMemoryPool(byte_count, mem);
}

Device_GPU::~Device_GPU() {}
#endif

// TODO we should be able to configure this carefully with a configuration
// script
// CPU -- 0 params
//     -- 50mb fxs
//     -- 50mb dEdfx
Device_CPU::Device_CPU(int my_id, int mb, bool shared) :
    Device(my_id, DeviceType::CPU, &cpu_mem), shmem(mem) {
  if (shared) shmem = new SharedAllocator();
  kSCALAR_MINUSONE = (float*) mem->malloc(sizeof(float));
  *kSCALAR_MINUSONE = -1;
  kSCALAR_ONE = (float*) mem->malloc(sizeof(float));
  *kSCALAR_ONE = 1;
  kSCALAR_ZERO = (float*) mem->malloc(sizeof(float));
  *kSCALAR_ZERO = 0;

  // Initialize the Eigen device
  edevice = new Eigen::DefaultDevice;

  // this is the big memory allocation. Do it in stages to make sure things are aligned.
  size_t byte_count = (size_t)((mb << 10)/3) << 10;
  for(size_t i = 0; i < 3; ++i)
    pools[i] = new AlignedMemoryPool(byte_count, mem);
}

Device_CPU::~Device_CPU() {}

} // namespace cnn
<|endoftext|>


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

#include "MemoryBuffer.h"

#include "internal.h"

#include <cstring>
#include <cstdlib>

using namespace tcam;

MemoryBuffer::MemoryBuffer (const struct tcam_image_buffer& buf, bool owns_memory)
    : is_own_memory(owns_memory), buffer(buf)
{
    tcam_log(TCAM_LOG_DEBUG, "Adress is %p", buffer.pData);

}

MemoryBuffer::MemoryBuffer (const VideoFormat& format, bool owns_memory)
    : is_own_memory(owns_memory), buffer()
{
    buffer.length = format.get_required_buffer_size();
    if (is_own_memory)
    {
        tcam_log(TCAM_LOG_INFO, "allocating data buffer");
        buffer.pData = (unsigned char*)malloc(buffer.length );
    }
    else
    {
        buffer.pData = nullptr;
    }
    buffer.format = format.get_struct();
    buffer.pitch = format.get_pitch_size();

    tcam_log(TCAM_LOG_DEBUG, "Adress is %p", buffer.pData);
}

MemoryBuffer::~MemoryBuffer ()
{
    if (is_own_memory)
    {
        if (buffer.pData != nullptr)
        {
            free(buffer.pData);
        }
    }
}

tcam_image_buffer MemoryBuffer::getImageBuffer ()
{
    return buffer;
}

void MemoryBuffer::set_image_buffer (tcam_image_buffer buf)
{
    this->buffer = buf;
}

unsigned char* MemoryBuffer::get_data ()
{
    return buffer.pData;
}

struct tcam_stream_statistics MemoryBuffer::get_statistics () const
{
    return buffer.statistics;
}

bool MemoryBuffer::set_statistics (const struct tcam_stream_statistics& stats)
{
    buffer.statistics = stats;;

    return true;
}

bool MemoryBuffer::lock ()
{
    buffer.lock_count++;
    return true;
}

bool MemoryBuffer::unlock ()
{
    if (buffer.lock_count >=1)
    {
        buffer.lock_count--;
    }
    return true;
}

bool MemoryBuffer::is_locked () const
{
    if (buffer.lock_count == 0)
    {
        return false;
    }
    return true;
}

bool MemoryBuffer::is_complete () const
{
    return tcam::is_buffer_complete(&this->buffer);
}

void MemoryBuffer::clear ()
{
    memset(buffer.pData, 0, buffer.length);
}
<commit_msg>Remove debug log messages in MemoryBuffer<commit_after>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "MemoryBuffer.h"

#include "internal.h"

#include <cstring>
#include <cstdlib>

using namespace tcam;

MemoryBuffer::MemoryBuffer (const struct tcam_image_buffer& buf, bool owns_memory)
    : is_own_memory(owns_memory), buffer(buf)
{}

MemoryBuffer::MemoryBuffer (const VideoFormat& format, bool owns_memory)
    : is_own_memory(owns_memory), buffer()
{
    buffer.length = format.get_required_buffer_size();
    if (is_own_memory)
    {
        tcam_log(TCAM_LOG_INFO, "allocating data buffer");
        buffer.pData = (unsigned char*)malloc(buffer.length );
    }
    else
    {
        buffer.pData = nullptr;
    }
    buffer.format = format.get_struct();
    buffer.pitch = format.get_pitch_size();
}

MemoryBuffer::~MemoryBuffer ()
{
    if (is_own_memory)
    {
        if (buffer.pData != nullptr)
        {
            free(buffer.pData);
        }
    }
}

tcam_image_buffer MemoryBuffer::getImageBuffer ()
{
    return buffer;
}

void MemoryBuffer::set_image_buffer (tcam_image_buffer buf)
{
    this->buffer = buf;
}

unsigned char* MemoryBuffer::get_data ()
{
    return buffer.pData;
}

struct tcam_stream_statistics MemoryBuffer::get_statistics () const
{
    return buffer.statistics;
}

bool MemoryBuffer::set_statistics (const struct tcam_stream_statistics& stats)
{
    buffer.statistics = stats;;

    return true;
}

bool MemoryBuffer::lock ()
{
    buffer.lock_count++;
    return true;
}

bool MemoryBuffer::unlock ()
{
    if (buffer.lock_count >=1)
    {
        buffer.lock_count--;
    }
    return true;
}

bool MemoryBuffer::is_locked () const
{
    if (buffer.lock_count == 0)
    {
        return false;
    }
    return true;
}

bool MemoryBuffer::is_complete () const
{
    return tcam::is_buffer_complete(&this->buffer);
}

void MemoryBuffer::clear ()
{
    memset(buffer.pData, 0, buffer.length);
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#if defined(WEBRTC_ANDROID)
#include "webrtc/modules/audio_device/android/audio_device_template.h"
#include "webrtc/modules/audio_device/android/audio_record_jni.h"
#include "webrtc/modules/audio_device/android/audio_track_jni.h"
#if !defined(WEBRTC_CHROMIUM_BUILD)
#include "webrtc/modules/audio_device/android/opensles_input.h"
#include "webrtc/modules/audio_device/android/opensles_output.h"
#endif
#endif

#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
#include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/voice_engine/voice_engine_impl.h"

namespace webrtc
{

// Counter to be ensure that we can add a correct ID in all static trace
// methods. It is not the nicest solution, especially not since we already
// have a counter in VoEBaseImpl. In other words, there is room for
// improvement here.
static int32_t gVoiceEngineInstanceCounter = 0;

VoiceEngine* GetVoiceEngine(const Config* config, bool owns_config)
{
#if (defined _WIN32)
  HMODULE hmod = LoadLibrary(TEXT("VoiceEngineTestingDynamic.dll"));

  if (hmod) {
    typedef VoiceEngine* (*PfnGetVoiceEngine)(void);
    PfnGetVoiceEngine pfn = (PfnGetVoiceEngine)GetProcAddress(
        hmod,"GetVoiceEngine");
    if (pfn) {
      VoiceEngine* self = pfn();
      if (owns_config) {
        delete config;
      }
      return (self);
    }
  }
#endif

    VoiceEngineImpl* self = new VoiceEngineImpl(config, owns_config);
    if (self != NULL)
    {
        self->AddRef();  // First reference.  Released in VoiceEngine::Delete.
        gVoiceEngineInstanceCounter++;
    }
    return self;
}

int VoiceEngineImpl::AddRef() {
  return ++_ref_count;
}

// This implements the Release() method for all the inherited interfaces.
int VoiceEngineImpl::Release() {
  int new_ref = --_ref_count;
  assert(new_ref >= 0);
  if (new_ref == 0) {
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, -1,
                 "VoiceEngineImpl self deleting (voiceEngine=0x%p)",
                 this);

    // Clear any pointers before starting destruction. Otherwise worker-
    // threads will still have pointers to a partially destructed object.
    // Example: AudioDeviceBuffer::RequestPlayoutData() can access a
    // partially deconstructed |_ptrCbAudioTransport| during destruction
    // if we don't call Terminate here.
    Terminate();
    delete this;
  }

  return new_ref;
}

VoiceEngine* VoiceEngine::Create() {
  Config* config = new Config();
  config->Set<AudioCodingModuleFactory>(new NewAudioCodingModuleFactory());

  return GetVoiceEngine(config, true);
}

VoiceEngine* VoiceEngine::Create(const Config& config) {
  return GetVoiceEngine(&config, false);
}

int VoiceEngine::SetTraceFilter(unsigned int filter)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
                 VoEId(gVoiceEngineInstanceCounter, -1),
                 "SetTraceFilter(filter=0x%x)", filter);

    // Remember old filter
    uint32_t oldFilter = Trace::level_filter();
    Trace::set_level_filter(filter);

    // If previous log was ignored, log again after changing filter
    if (kTraceNone == oldFilter)
    {
        WEBRTC_TRACE(kTraceApiCall, kTraceVoice, -1,
                     "SetTraceFilter(filter=0x%x)", filter);
    }

    return 0;
}

int VoiceEngine::SetTraceFile(const char* fileNameUTF8,
                              bool addFileCounter)
{
    int ret = Trace::SetTraceFile(fileNameUTF8, addFileCounter);
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
                 VoEId(gVoiceEngineInstanceCounter, -1),
                 "SetTraceFile(fileNameUTF8=%s, addFileCounter=%d)",
                 fileNameUTF8, addFileCounter);
    return (ret);
}

int VoiceEngine::SetTraceCallback(TraceCallback* callback)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
                 VoEId(gVoiceEngineInstanceCounter, -1),
                 "SetTraceCallback(callback=0x%x)", callback);
    return (Trace::SetTraceCallback(callback));
}

bool VoiceEngine::Delete(VoiceEngine*& voiceEngine)
{
    if (voiceEngine == NULL)
        return false;

    VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
    // Release the reference that was added in GetVoiceEngine.
    int ref = s->Release();
    voiceEngine = NULL;

    if (ref != 0) {
        WEBRTC_TRACE(kTraceWarning, kTraceVoice, -1,
            "VoiceEngine::Delete did not release the very last reference.  "
            "%d references remain.", ref);
    }

    return true;
}

#if !defined(WEBRTC_CHROMIUM_BUILD)
int VoiceEngine::SetAndroidObjects(void* javaVM, void* env, void* context)
{
#ifdef WEBRTC_ANDROID
#ifdef WEBRTC_ANDROID_OPENSLES
  typedef AudioDeviceTemplate<OpenSlesInput, OpenSlesOutput>
      AudioDeviceInstance;
#else
  typedef AudioDeviceTemplate<AudioRecordJni, AudioTrackJni>
      AudioDeviceInstance;
#endif
  if (javaVM && env && context) {
    AudioDeviceInstance::SetAndroidAudioDeviceObjects(javaVM, env, context);
  } else {
    AudioDeviceInstance::ClearAndroidAudioDeviceObjects();
  }
  return 0;
#else
  return -1;
#endif
}
#endif

}  // namespace webrtc
<commit_msg>Revert "Make VoiceEngine choose ACM2 by default"<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#if defined(WEBRTC_ANDROID)
#include "webrtc/modules/audio_device/android/audio_device_template.h"
#include "webrtc/modules/audio_device/android/audio_record_jni.h"
#include "webrtc/modules/audio_device/android/audio_track_jni.h"
#if !defined(WEBRTC_CHROMIUM_BUILD)
#include "webrtc/modules/audio_device/android/opensles_input.h"
#include "webrtc/modules/audio_device/android/opensles_output.h"
#endif
#endif

#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
#include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/voice_engine/voice_engine_impl.h"

namespace webrtc
{

// Counter to be ensure that we can add a correct ID in all static trace
// methods. It is not the nicest solution, especially not since we already
// have a counter in VoEBaseImpl. In other words, there is room for
// improvement here.
static int32_t gVoiceEngineInstanceCounter = 0;

VoiceEngine* GetVoiceEngine(const Config* config, bool owns_config)
{
#if (defined _WIN32)
  HMODULE hmod = LoadLibrary(TEXT("VoiceEngineTestingDynamic.dll"));

  if (hmod) {
    typedef VoiceEngine* (*PfnGetVoiceEngine)(void);
    PfnGetVoiceEngine pfn = (PfnGetVoiceEngine)GetProcAddress(
        hmod,"GetVoiceEngine");
    if (pfn) {
      VoiceEngine* self = pfn();
      if (owns_config) {
        delete config;
      }
      return (self);
    }
  }
#endif

    VoiceEngineImpl* self = new VoiceEngineImpl(config, owns_config);
    if (self != NULL)
    {
        self->AddRef();  // First reference.  Released in VoiceEngine::Delete.
        gVoiceEngineInstanceCounter++;
    }
    return self;
}

int VoiceEngineImpl::AddRef() {
  return ++_ref_count;
}

// This implements the Release() method for all the inherited interfaces.
int VoiceEngineImpl::Release() {
  int new_ref = --_ref_count;
  assert(new_ref >= 0);
  if (new_ref == 0) {
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, -1,
                 "VoiceEngineImpl self deleting (voiceEngine=0x%p)",
                 this);

    // Clear any pointers before starting destruction. Otherwise worker-
    // threads will still have pointers to a partially destructed object.
    // Example: AudioDeviceBuffer::RequestPlayoutData() can access a
    // partially deconstructed |_ptrCbAudioTransport| during destruction
    // if we don't call Terminate here.
    Terminate();
    delete this;
  }

  return new_ref;
}

VoiceEngine* VoiceEngine::Create() {
  Config* config = new Config();
  config->Set<AudioCodingModuleFactory>(new AudioCodingModuleFactory());

  return GetVoiceEngine(config, true);
}

VoiceEngine* VoiceEngine::Create(const Config& config) {
  return GetVoiceEngine(&config, false);
}

int VoiceEngine::SetTraceFilter(unsigned int filter)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
                 VoEId(gVoiceEngineInstanceCounter, -1),
                 "SetTraceFilter(filter=0x%x)", filter);

    // Remember old filter
    uint32_t oldFilter = Trace::level_filter();
    Trace::set_level_filter(filter);

    // If previous log was ignored, log again after changing filter
    if (kTraceNone == oldFilter)
    {
        WEBRTC_TRACE(kTraceApiCall, kTraceVoice, -1,
                     "SetTraceFilter(filter=0x%x)", filter);
    }

    return 0;
}

int VoiceEngine::SetTraceFile(const char* fileNameUTF8,
                              bool addFileCounter)
{
    int ret = Trace::SetTraceFile(fileNameUTF8, addFileCounter);
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
                 VoEId(gVoiceEngineInstanceCounter, -1),
                 "SetTraceFile(fileNameUTF8=%s, addFileCounter=%d)",
                 fileNameUTF8, addFileCounter);
    return (ret);
}

int VoiceEngine::SetTraceCallback(TraceCallback* callback)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
                 VoEId(gVoiceEngineInstanceCounter, -1),
                 "SetTraceCallback(callback=0x%x)", callback);
    return (Trace::SetTraceCallback(callback));
}

bool VoiceEngine::Delete(VoiceEngine*& voiceEngine)
{
    if (voiceEngine == NULL)
        return false;

    VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
    // Release the reference that was added in GetVoiceEngine.
    int ref = s->Release();
    voiceEngine = NULL;

    if (ref != 0) {
        WEBRTC_TRACE(kTraceWarning, kTraceVoice, -1,
            "VoiceEngine::Delete did not release the very last reference.  "
            "%d references remain.", ref);
    }

    return true;
}

#if !defined(WEBRTC_CHROMIUM_BUILD)
int VoiceEngine::SetAndroidObjects(void* javaVM, void* env, void* context)
{
#ifdef WEBRTC_ANDROID
#ifdef WEBRTC_ANDROID_OPENSLES
  typedef AudioDeviceTemplate<OpenSlesInput, OpenSlesOutput>
      AudioDeviceInstance;
#else
  typedef AudioDeviceTemplate<AudioRecordJni, AudioTrackJni>
      AudioDeviceInstance;
#endif
  if (javaVM && env && context) {
    AudioDeviceInstance::SetAndroidAudioDeviceObjects(javaVM, env, context);
  } else {
    AudioDeviceInstance::ClearAndroidAudioDeviceObjects();
  }
  return 0;
#else
  return -1;
#endif
}
#endif

}  // namespace webrtc
<|endoftext|>


<commit_before>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include <vistk/pipeline/config.h>
#include <vistk/pipeline/modules.h>
#include <vistk/pipeline/process.h>
#include <vistk/pipeline/process_exception.h>
#include <vistk/pipeline/process_registry.h>
#include <vistk/pipeline/process_registry_exception.h>
#include <vistk/pipeline/types.h>

#include <boost/foreach.hpp>

#include <exception>
#include <iostream>

int
main()
{
  vistk::process_registry_t reg = vistk::process_registry::self();

  try
  {
    vistk::load_known_modules();
  }
  catch (vistk::process_type_already_exists_exception& e)
  {
    std::cerr << "Error: Duplicate process names: " << e.what() << std::endl;
  }
  catch (vistk::pipeline_exception& e)
  {
    std::cerr << "Error: Failed to load modules: " << e.what() << std::endl;
  }
  catch (std::exception& e)
  {
    std::cerr << "Error: Unexpected exception when loading modules: " << e.what() << std::endl;

    return 1;
  }

  vistk::process::name_t const expected_name = vistk::process::name_t("expected_name");

  vistk::process_registry::types_t const types = reg->types();

  vistk::config_t config = vistk::config::empty_config();
  config->set_value(vistk::process::config_name, expected_name);

  BOOST_FOREACH (vistk::process_registry::type_t const& type, types)
  {
    vistk::process_t process;

    try
    {
      process = reg->create_process(type, config);
    }
    catch (vistk::no_such_process_type_exception& e)
    {
      std::cerr << "Error: Failed to create process: " << e.what() << std::endl;

      continue;
    }
    catch (std::exception& e)
    {
      std::cerr << "Error: Unexpected exception when creating process: " << e.what() << std::endl;
    }

    if (!process)
    {
      std::cerr << "Error: Received NULL process (" << type << ")" << std::endl;

      continue;
    }

    if (reg->description(type).empty())
    {
      std::cerr << "Error: The description is empty" << std::endl;
    }

    if (process->name() != expected_name)
    {
      std::cerr << "Error: Name (" << process->name() << ") "
                << "does not match expected name: " << expected_name << std::endl;
    }

    if (process->type().empty())
    {
      std::cerr << "Error: The type is empty" << std::endl;
    }

    vistk::config::keys_t const keys = process->available_config();

    BOOST_FOREACH (vistk::config::key_t const& key, keys)
    {
      try
      {
        process->config_default(key);
      }
      catch (vistk::unknown_configuration_value_exception& e)
      {
        std::cerr << "Error: Failed to get a default for "
                  << type << vistk::config::block_sep << key
                  << ": " << e.what() << std::endl;
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when querying for default "
                  << "(" << type << vistk::config::block_sep
                  << key << "): " << e.what() << std::endl;
      }

      try
      {
        process->config_description(key);
      }
      catch (vistk::unknown_configuration_value_exception& e)
      {
        std::cerr << "Error: Failed to get a description for "
                  << type << vistk::config::block_sep << key
                  << ": " << e.what() << std::endl;
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when querying for description "
                  << "(" << type << vistk::config::block_sep
                  << key << "): " << e.what() << std::endl;
      }
    }

    vistk::process::ports_t const iports = process->input_ports();

    BOOST_FOREACH (vistk::process::port_t const& port, iports)
    {
      try
      {
        process->input_port_type(port);
      }
      catch (vistk::no_such_port_exception& e)
      {
        std::cerr << "Error: Failed to get a type for input port "
                  << type << "." << port << ": " << e.what() << std::endl;
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when querying for input port type "
                  << "(" << type << "." << port << "): " << e.what() << std::endl;
      }

      try
      {
        process->input_port_description(port);
      }
      catch (vistk::no_such_port_exception& e)
      {
        std::cerr << "Error: Failed to get a description for input port "
                  << type << "." << port << ": " << e.what() << std::endl;
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when querying for input port description "
                  << "(" << type << "." << port << "): " << e.what() << std::endl;
      }
    }

    vistk::process::ports_t const oports = process->output_ports();

    BOOST_FOREACH (vistk::process::port_t const& port, oports)
    {
      try
      {
        process->output_port_type(port);
      }
      catch (vistk::no_such_port_exception& e)
      {
        std::cerr << "Error: Failed to get a type for output port "
                  << type << "." << port << ": " << e.what() << std::endl;
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when querying for output port type "
                  << "(" << type << "." << port << "): " << e.what() << std::endl;
      }

      try
      {
        process->output_port_description(port);
      }
      catch (vistk::no_such_port_exception& e)
      {
        std::cerr << "Error: Failed to get a description for output port "
                  << type << "." << port << ": " << e.what() << std::endl;
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when querying for output port description "
                  << "(" << type << "." << port << "): " << e.what() << std::endl;
      }
    }

    // Test for proper exceptions on invalid config requests.
    {
      vistk::config::key_t const non_existent_config = vistk::config::key_t("does_not_exist");

      try
      {
        process->config_default(non_existent_config);
      }
      catch (vistk::unknown_configuration_value_exception& e)
      {
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when "
                  << "requesting default for non-existent config: "
                  << e.what() << std::endl;
      }

      try
      {
        process->config_description(non_existent_config);
      }
      catch (vistk::unknown_configuration_value_exception& e)
      {
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when "
                  << "requesting description for non-existent config: "
                  << e.what() << std::endl;
      }
    }

    // Test for proper exceptions on invalid port requests.
    {
      vistk::process::port_t const non_existent_port = vistk::process::port_t("does_not_exist");

      // Input ports.
      {
        try
        {
          process->input_port_type(non_existent_port);
        }
        catch (vistk::no_such_port_exception& e)
        {
        }
        catch (std::exception& e)
        {
          std::cerr << "Error: Unexpected exception when "
                    << "requesting type on non-existent input port: "
                    << e.what() << std::endl;
        }

        try
        {
          process->input_port_description(non_existent_port);
        }
        catch (vistk::no_such_port_exception& e)
        {
        }
        catch (std::exception& e)
        {
          std::cerr << "Error: Unexpected exception when "
                    << "requesting description for non-existent input port: "
                    << e.what() << std::endl;
        }

        vistk::edge_t edge = vistk::edge_t(new vistk::edge(config));

        try
        {
          process->connect_input_port(non_existent_port, edge);
        }
        catch (vistk::no_such_port_exception& e)
        {
        }
        catch (std::exception& e)
        {
          std::cerr << "Error: Unexpected exception when "
                    << "requesting connection to non-existent input port: "
                    << e.what() << std::endl;
        }
      }

      // Output ports.
      {
        try
        {
          process->output_port_type(non_existent_port);
        }
        catch (vistk::no_such_port_exception& e)
        {
        }
        catch (std::exception& e)
        {
          std::cerr << "Error: Unexpected exception when "
                    << "requesting type on non-existent output port: "
                    << e.what() << std::endl;
        }

        try
        {
          process->output_port_description(non_existent_port);
        }
        catch (vistk::no_such_port_exception& e)
        {
        }
        catch (std::exception& e)
        {
          std::cerr << "Error: Unexpected exception when "
                    << "requesting description for non-existent output port: "
                    << e.what() << std::endl;
        }

        vistk::edge_t edge = vistk::edge_t(new vistk::edge(config));

        try
        {
          process->connect_output_port(non_existent_port, edge);
        }
        catch (vistk::no_such_port_exception& e)
        {
        }
        catch (std::exception& e)
        {
          std::cerr << "Error: Unexpected exception when "
                    << "requesting connection to non-existent output port: "
                    << e.what() << std::endl;
        }
      }
    }
  }

  // Check exceptions for unknown types.
  {
    vistk::process_registry::type_t const non_existent_process = vistk::process_registry::type_t("no_such_process");

    try
    {
      reg->create_process(non_existent_process, config);
    }
    catch (vistk::no_such_process_type_exception& e)
    {
    }
    catch (std::exception& e)
    {
      std::cerr << "Error: Unexpected exception when "
                << "requesting a non-existent process type: "
                << e.what() << std::endl;
    }

    try
    {
      reg->description(non_existent_process);
    }
    catch (vistk::no_such_process_type_exception& e)
    {
    }
    catch (std::exception& e)
    {
      std::cerr << "Error: Unexpected exception when "
                << "requesting a description of a non-existent process type: "
                << e.what() << std::endl;
    }
  }

  return 0;
}
<commit_msg>Convert process introspection test to use macro<commit_after>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include <test_common.h>

#include <vistk/pipeline/config.h>
#include <vistk/pipeline/modules.h>
#include <vistk/pipeline/process.h>
#include <vistk/pipeline/process_exception.h>
#include <vistk/pipeline/process_registry.h>
#include <vistk/pipeline/process_registry_exception.h>
#include <vistk/pipeline/types.h>

#include <boost/foreach.hpp>

#include <exception>
#include <iostream>

int
main()
{
  vistk::process_registry_t reg = vistk::process_registry::self();

  try
  {
    vistk::load_known_modules();
  }
  catch (vistk::process_type_already_exists_exception& e)
  {
    std::cerr << "Error: Duplicate process names: " << e.what() << std::endl;
  }
  catch (vistk::pipeline_exception& e)
  {
    std::cerr << "Error: Failed to load modules: " << e.what() << std::endl;
  }
  catch (std::exception& e)
  {
    std::cerr << "Error: Unexpected exception when loading modules: " << e.what() << std::endl;

    return 1;
  }

  vistk::process::name_t const expected_name = vistk::process::name_t("expected_name");

  vistk::process_registry::types_t const types = reg->types();

  vistk::config_t config = vistk::config::empty_config();
  config->set_value(vistk::process::config_name, expected_name);

  BOOST_FOREACH (vistk::process_registry::type_t const& type, types)
  {
    vistk::process_t process;

    try
    {
      process = reg->create_process(type, config);
    }
    catch (vistk::no_such_process_type_exception& e)
    {
      std::cerr << "Error: Failed to create process: " << e.what() << std::endl;

      continue;
    }
    catch (std::exception& e)
    {
      std::cerr << "Error: Unexpected exception when creating process: " << e.what() << std::endl;
    }

    if (!process)
    {
      std::cerr << "Error: Received NULL process (" << type << ")" << std::endl;

      continue;
    }

    if (reg->description(type).empty())
    {
      std::cerr << "Error: The description is empty" << std::endl;
    }

    if (process->name() != expected_name)
    {
      std::cerr << "Error: Name (" << process->name() << ") "
                << "does not match expected name: " << expected_name << std::endl;
    }

    if (process->type().empty())
    {
      std::cerr << "Error: The type is empty" << std::endl;
    }

    vistk::config::keys_t const keys = process->available_config();

    BOOST_FOREACH (vistk::config::key_t const& key, keys)
    {
      try
      {
        process->config_default(key);
      }
      catch (vistk::unknown_configuration_value_exception& e)
      {
        std::cerr << "Error: Failed to get a default for "
                  << type << vistk::config::block_sep << key
                  << ": " << e.what() << std::endl;
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when querying for default "
                  << "(" << type << vistk::config::block_sep
                  << key << "): " << e.what() << std::endl;
      }

      try
      {
        process->config_description(key);
      }
      catch (vistk::unknown_configuration_value_exception& e)
      {
        std::cerr << "Error: Failed to get a description for "
                  << type << vistk::config::block_sep << key
                  << ": " << e.what() << std::endl;
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when querying for description "
                  << "(" << type << vistk::config::block_sep
                  << key << "): " << e.what() << std::endl;
      }
    }

    vistk::process::ports_t const iports = process->input_ports();

    BOOST_FOREACH (vistk::process::port_t const& port, iports)
    {
      try
      {
        process->input_port_type(port);
      }
      catch (vistk::no_such_port_exception& e)
      {
        std::cerr << "Error: Failed to get a type for input port "
                  << type << "." << port << ": " << e.what() << std::endl;
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when querying for input port type "
                  << "(" << type << "." << port << "): " << e.what() << std::endl;
      }

      try
      {
        process->input_port_description(port);
      }
      catch (vistk::no_such_port_exception& e)
      {
        std::cerr << "Error: Failed to get a description for input port "
                  << type << "." << port << ": " << e.what() << std::endl;
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when querying for input port description "
                  << "(" << type << "." << port << "): " << e.what() << std::endl;
      }
    }

    vistk::process::ports_t const oports = process->output_ports();

    BOOST_FOREACH (vistk::process::port_t const& port, oports)
    {
      try
      {
        process->output_port_type(port);
      }
      catch (vistk::no_such_port_exception& e)
      {
        std::cerr << "Error: Failed to get a type for output port "
                  << type << "." << port << ": " << e.what() << std::endl;
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when querying for output port type "
                  << "(" << type << "." << port << "): " << e.what() << std::endl;
      }

      try
      {
        process->output_port_description(port);
      }
      catch (vistk::no_such_port_exception& e)
      {
        std::cerr << "Error: Failed to get a description for output port "
                  << type << "." << port << ": " << e.what() << std::endl;
      }
      catch (std::exception& e)
      {
        std::cerr << "Error: Unexpected exception when querying for output port description "
                  << "(" << type << "." << port << "): " << e.what() << std::endl;
      }
    }

    // Test for proper exceptions on invalid config requests.
    {
      vistk::config::key_t const non_existent_config = vistk::config::key_t("does_not_exist");

      EXPECT_EXCEPTION(vistk::unknown_configuration_value_exception,
                       process->config_default(non_existent_config),
                       "requesting the default for a non-existent config");

      EXPECT_EXCEPTION(vistk::unknown_configuration_value_exception,
                       process->config_description(non_existent_config),
                       "requesting a description for a non-existent config");
    }

    // Test for proper exceptions on invalid port requests.
    {
      vistk::process::port_t const non_existent_port = vistk::process::port_t("does_not_exist");

      // Input ports.
      {
        EXPECT_EXCEPTION(vistk::no_such_port_exception,
                         process->input_port_type(non_existent_port),
                         "requesting the type of a non-existent input port");

        EXPECT_EXCEPTION(vistk::no_such_port_exception,
                         process->input_port_description(non_existent_port),
                         "requesting a description for a non-existent input port");

        vistk::edge_t edge = vistk::edge_t(new vistk::edge(config));

        EXPECT_EXCEPTION(vistk::no_such_port_exception,
                         process->connect_input_port(non_existent_port, edge),
                         "requesting a connection to a non-existent input port");
      }

      // Output ports.
      {
        EXPECT_EXCEPTION(vistk::no_such_port_exception,
                         process->output_port_type(non_existent_port),
                         "requesting the type of a non-existent output port");

        EXPECT_EXCEPTION(vistk::no_such_port_exception,
                         process->output_port_description(non_existent_port),
                         "requesting a description for a non-existent output port");

        vistk::edge_t edge = vistk::edge_t(new vistk::edge(config));

        EXPECT_EXCEPTION(vistk::no_such_port_exception,
                         process->connect_output_port(non_existent_port, edge),
                         "requesting a connection to a non-existent output port");
      }
    }
  }

  // Check exceptions for unknown types.
  {
    vistk::process_registry::type_t const non_existent_process = vistk::process_registry::type_t("no_such_process");

    EXPECT_EXCEPTION(vistk::no_such_process_type_exception,
                     reg->create_process(non_existent_process, config),
                     "requesting an non-existent process type");

    EXPECT_EXCEPTION(vistk::no_such_process_type_exception,
                     reg->description(non_existent_process),
                     "requesting an non-existent process type");
  }

  return 0;
}
<|endoftext|>


<commit_before>/**
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you 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.
 */

/**
 * @file GlobalPlugin.cc
 */
#include "atscppapi/GlobalPlugin.h"
#include <ts/ts.h>
#include <cstddef>
#include <cassert>
#include "atscppapi/noncopyable.h"
#include "utils_internal.h"
#include "logging_internal.h"

using namespace atscppapi;

/**
 * @private
 */
struct atscppapi::GlobalPluginState : noncopyable {
  TSCont cont_;
  GlobalPlugin *global_plugin_;
  bool ignore_internal_transactions_;

  GlobalPluginState(GlobalPlugin *global_plugin, bool ignore_internal_transactions)
    : global_plugin_(global_plugin), ignore_internal_transactions_(ignore_internal_transactions)
  {
  }
};

namespace
{
static int
handleGlobalPluginEvents(TSCont cont, TSEvent event, void *edata)
{
  TSHttpTxn txn            = static_cast<TSHttpTxn>(edata);
  GlobalPluginState *state = static_cast<GlobalPluginState *>(TSContDataGet(cont));
  if (state->ignore_internal_transactions_ && TSHttpTxnIsInternal(txn)) {
    LOG_DEBUG("Ignoring event %d on internal transaction %p for global plugin %p", event, txn, state->global_plugin_);
    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
  } else {
    LOG_DEBUG("Invoking global plugin %p for event %d on transaction %p", state->global_plugin_, event, txn);
    utils::internal::invokePluginForEvent(state->global_plugin_, txn, event);
  }
  return 0;
}

} /* anonymous namespace */

GlobalPlugin::GlobalPlugin(bool ignore_internal_transactions)
{
  utils::internal::initTransactionManagement();
  state_        = new GlobalPluginState(this, ignore_internal_transactions);
  TSMutex mutex = nullptr;
  state_->cont_ = TSContCreate(handleGlobalPluginEvents, mutex);
  TSContDataSet(state_->cont_, static_cast<void *>(state_));
}

GlobalPlugin::~GlobalPlugin()
{
  TSContDestroy(state_->cont_);
  delete state_;
}

void
GlobalPlugin::registerHook(Plugin::HookType hook_type)
{
  TSHttpHookID hook_id = utils::internal::convertInternalHookToTsHook(hook_type);
  TSHttpHookAdd(hook_id, state_->cont_);
  LOG_DEBUG("Registered global plugin %p for hook %s", this, HOOK_TYPE_STRINGS[hook_type].c_str());
}
<commit_msg>coverity 1200037: Uninitialized pointer field<commit_after>/**
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you 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.
 */

/**
 * @file GlobalPlugin.cc
 */
#include "atscppapi/GlobalPlugin.h"
#include <ts/ts.h>
#include <cstddef>
#include <cassert>
#include "atscppapi/noncopyable.h"
#include "utils_internal.h"
#include "logging_internal.h"

using namespace atscppapi;

/**
 * @private
 */
struct atscppapi::GlobalPluginState : noncopyable {
  TSCont cont_ = nullptr;
  GlobalPlugin *global_plugin_;
  bool ignore_internal_transactions_;

  GlobalPluginState(GlobalPlugin *global_plugin, bool ignore_internal_transactions)
    : global_plugin_(global_plugin), ignore_internal_transactions_(ignore_internal_transactions)
  {
  }
};

namespace
{
static int
handleGlobalPluginEvents(TSCont cont, TSEvent event, void *edata)
{
  TSHttpTxn txn            = static_cast<TSHttpTxn>(edata);
  GlobalPluginState *state = static_cast<GlobalPluginState *>(TSContDataGet(cont));
  if (state->ignore_internal_transactions_ && TSHttpTxnIsInternal(txn)) {
    LOG_DEBUG("Ignoring event %d on internal transaction %p for global plugin %p", event, txn, state->global_plugin_);
    TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE);
  } else {
    LOG_DEBUG("Invoking global plugin %p for event %d on transaction %p", state->global_plugin_, event, txn);
    utils::internal::invokePluginForEvent(state->global_plugin_, txn, event);
  }
  return 0;
}

} /* anonymous namespace */

GlobalPlugin::GlobalPlugin(bool ignore_internal_transactions)
{
  utils::internal::initTransactionManagement();
  state_        = new GlobalPluginState(this, ignore_internal_transactions);
  TSMutex mutex = nullptr;
  state_->cont_ = TSContCreate(handleGlobalPluginEvents, mutex);
  TSContDataSet(state_->cont_, static_cast<void *>(state_));
}

GlobalPlugin::~GlobalPlugin()
{
  TSContDestroy(state_->cont_);
  delete state_;
}

void
GlobalPlugin::registerHook(Plugin::HookType hook_type)
{
  TSHttpHookID hook_id = utils::internal::convertInternalHookToTsHook(hook_type);
  TSHttpHookAdd(hook_id, state_->cont_);
  LOG_DEBUG("Registered global plugin %p for hook %s", this, HOOK_TYPE_STRINGS[hook_type].c_str());
}
<|endoftext|>