<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief arango benchmark tool
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "BasicsC/common.h"

#include <stdio.h>
#include <iomanip>

#include "ArangoShell/ArangoClient.h"
#include "Basics/Mutex.h"
#include "Basics/MutexLocker.h"
#include "Basics/ProgramOptions.h"
#include "Basics/ProgramOptionsDescription.h"
#include "Basics/StringUtils.h"
#include "BasicsC/init.h"
#include "BasicsC/logging.h"
#include "BasicsC/random.h"
#include "BasicsC/tri-strings.h"
#include "BasicsC/string-buffer.h"
#include "BasicsC/terminal-utils.h"
#include "Rest/Endpoint.h"
#include "Rest/HttpRequest.h"
#include "Rest/InitialiseRest.h"
#include "SimpleHttpClient/SimpleHttpClient.h"
#include "SimpleHttpClient/SimpleHttpResult.h"
#include "Benchmark/BenchmarkCounter.h"
#include "Benchmark/BenchmarkOperation.h"
#include "Benchmark/BenchmarkThread.h"

using namespace std;
using namespace triagens::basics;
using namespace triagens::httpclient;
using namespace triagens::rest;
using namespace triagens::arango;
using namespace triagens::arangob;

// -----------------------------------------------------------------------------
// --SECTION--                                                 private variables
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Benchmark
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief base class for clients
////////////////////////////////////////////////////////////////////////////////

ArangoClient BaseClient;

////////////////////////////////////////////////////////////////////////////////
/// @brief started counter
////////////////////////////////////////////////////////////////////////////////

static atomic<int> Started;

////////////////////////////////////////////////////////////////////////////////
/// @brief mutex for start counter
////////////////////////////////////////////////////////////////////////////////

Mutex StartMutex;

////////////////////////////////////////////////////////////////////////////////
/// @brief send asychronous requests
////////////////////////////////////////////////////////////////////////////////

static bool Async = false;

////////////////////////////////////////////////////////////////////////////////
/// @brief number of operations in one batch
////////////////////////////////////////////////////////////////////////////////

static int BatchSize = 0;

////////////////////////////////////////////////////////////////////////////////
/// @brief collection to use
////////////////////////////////////////////////////////////////////////////////

static string Collection = "ArangoBenchmark";

////////////////////////////////////////////////////////////////////////////////
/// @brief complexity parameter for tests
////////////////////////////////////////////////////////////////////////////////

static uint64_t Complexity = 1;

////////////////////////////////////////////////////////////////////////////////
/// @brief concurrency
////////////////////////////////////////////////////////////////////////////////

static int Concurrency = 1;

////////////////////////////////////////////////////////////////////////////////
/// @brief use a startup delay
////////////////////////////////////////////////////////////////////////////////

static bool Delay = false;

////////////////////////////////////////////////////////////////////////////////
/// @brief use HTTP keep-alive
////////////////////////////////////////////////////////////////////////////////

static bool KeepAlive = true;

////////////////////////////////////////////////////////////////////////////////
/// @brief number of operations to perform
////////////////////////////////////////////////////////////////////////////////

static int Operations = 1000;

////////////////////////////////////////////////////////////////////////////////
/// @brief display progress
////////////////////////////////////////////////////////////////////////////////

static bool Progress = true;

////////////////////////////////////////////////////////////////////////////////
/// @brief test case to use
////////////////////////////////////////////////////////////////////////////////

static string TestCase = "version";

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief includes all the test cases
////////////////////////////////////////////////////////////////////////////////

#include "Benchmark/test-cases.h"

// -----------------------------------------------------------------------------
// --SECTION--                                                 private functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Benchmark
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief update the number of ready threads. this is a callback function
/// that is called by each thread after it is created
////////////////////////////////////////////////////////////////////////////////

static void UpdateStartCounter () {
  ++Started;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get the value of the number of started threads counter
////////////////////////////////////////////////////////////////////////////////

static int GetStartCounter () {
  return Started;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief print a status line (if ! quiet)
////////////////////////////////////////////////////////////////////////////////

static void Status (const string& value) {
  if (! BaseClient.quiet()) {
    cout << value << endl;
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief parses the program options
////////////////////////////////////////////////////////////////////////////////

static void ParseProgramOptions (int argc, char* argv[]) {
  ProgramOptionsDescription description("STANDARD options");

  description
    ("async", &Async, "send asychronous requests")
    ("concurrency", &Concurrency, "number of parallel connections")
    ("requests", &Operations, "total number of operations")
    ("batch-size", &BatchSize, "number of operations in one batch (0 disables batching)")
    ("keep-alive", &KeepAlive, "use HTTP keep-alive")
    ("collection", &Collection, "collection name to use in tests")
    ("test-case", &TestCase, "test case to use")
    ("complexity", &Complexity, "complexity parameter for the test")
    ("delay", &Delay, "use a startup delay (necessary only when run in series)")
    ("progress", &Progress, "show progress")
  ;

  BaseClient.setupGeneral(description);
  BaseClient.setupServer(description);

  vector<string> arguments;
  description.arguments(&arguments);

  ProgramOptions options;
  BaseClient.parse(options, description, "--concurrency <concurrency> --requests <request> --test-case <case> ...", argc, argv, "arangob.conf");
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                  public functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Benchmark
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief startup and exit functions
////////////////////////////////////////////////////////////////////////////////

static void arangobEntryFunction ();
static void arangobExitFunction (int, void*);

#ifdef _WIN32

// .............................................................................
// Call this function to do various initialisations for windows only
// .............................................................................

void arangobEntryFunction () {
  int maxOpenFiles = 1024;
  int res = 0;

  // ...........................................................................
  // Uncomment this to call this for extended debug information.
  // If you familiar with valgrind ... then this is not like that, however
  // you do get some similar functionality.
  // ...........................................................................
  //res = initialiseWindows(TRI_WIN_INITIAL_SET_DEBUG_FLAG, 0);

  res = initialiseWindows(TRI_WIN_INITIAL_SET_INVALID_HANLE_HANDLER, 0);
  if (res != 0) {
    _exit(1);
  }

  res = initialiseWindows(TRI_WIN_INITIAL_SET_MAX_STD_IO,(const char*)(&maxOpenFiles));
  if (res != 0) {
    _exit(1);
  }

  res = initialiseWindows(TRI_WIN_INITIAL_WSASTARTUP_FUNCTION_CALL, 0);
  if (res != 0) {
    _exit(1);
  }

  TRI_Application_Exit_SetExit(arangobExitFunction);
}

static void arangobExitFunction (int exitCode, void* data) {
  int res = 0;
  // ...........................................................................
  // TODO: need a terminate function for windows to be called and cleanup
  // any windows specific stuff.
  // ...........................................................................

  res = finaliseWindows(TRI_WIN_FINAL_WSASTARTUP_FUNCTION_CALL, 0);

  if (res != 0) {
    exit(1);
  }

  exit(exitCode);
}
#else

static void arangobEntryFunction () {
}

static void arangobExitFunction (int exitCode, void* data) {
}

#endif

////////////////////////////////////////////////////////////////////////////////
/// @brief main
////////////////////////////////////////////////////////////////////////////////

int main (int argc, char* argv[]) {
  int ret = EXIT_SUCCESS;

  arangobEntryFunction();

  TRIAGENS_C_INITIALISE(argc, argv);
  TRIAGENS_REST_INITIALISE(argc, argv);

  TRI_InitialiseLogging(false);

  BaseClient.setEndpointString(Endpoint::getDefaultEndpoint());

  // .............................................................................
  // parse the program options
  // .............................................................................

  ParseProgramOptions(argc, argv);

  // .............................................................................
  // set-up client connection
  // .............................................................................

  BaseClient.createEndpoint();

  if (BaseClient.endpointServer() == 0) {
    LOG_FATAL_AND_EXIT("invalid value for --server.endpoint ('%s')", BaseClient.endpointString().c_str());
  }

  BenchmarkOperation* testCase = GetTestCase(TestCase);

  if (testCase == 0) {
    LOG_FATAL_AND_EXIT("invalid test case name '%s'", TestCase.c_str());
    return EXIT_FAILURE; // will not be reached
  }

  Status("starting threads...");

  BenchmarkCounter<unsigned long> operationsCounter(0, (unsigned long) Operations);
  ConditionVariable startCondition;

  vector<Endpoint*> endpoints;
  vector<BenchmarkThread*> threads;

  const double stepSize = (double) Operations / (double) Concurrency;
  int64_t realStep = (int64_t) stepSize;
  if (stepSize - (double) ((int64_t) stepSize) > 0.0) {
    realStep++;
  }
  if (realStep % 1000 != 0) {
    realStep += 1000 - (realStep % 1000);
  }
  // add some more offset so we don't get into trouble with threads of different speed
  realStep += 10000;

  // start client threads
  for (int i = 0; i < Concurrency; ++i) {
    Endpoint* endpoint = Endpoint::clientFactory(BaseClient.endpointString());
    endpoints.push_back(endpoint);

    BenchmarkThread* thread = new BenchmarkThread(testCase,
        &startCondition,
        &UpdateStartCounter,
        i,
        (unsigned long) BatchSize,
        &operationsCounter,
        endpoint,
        BaseClient.databaseName(),
        BaseClient.username(),
        BaseClient.password(),
        BaseClient.requestTimeout(),
        BaseClient.connectTimeout(),
        BaseClient.sslProtocol(),
        KeepAlive,
        Async);

    threads.push_back(thread);
    thread->setOffset((size_t) (i * realStep));
    thread->start();
  }

  // give all threads a chance to start so they will not miss the broadcast
  while (GetStartCounter() < Concurrency) {
    usleep(5000);
  }

  if (Delay) {
    Status("sleeping (startup delay)...");
    sleep(10);
  }
  Status("executing tests...");

  double start = TRI_microtime();

  // broadcast the start signal to all threads
  {
    ConditionLocker guard(&startCondition);
    guard.broadcast();
  }

  const size_t stepValue = (Operations / 20);
  size_t nextReportValue = stepValue;

  if (nextReportValue < 100) {
    nextReportValue = 100;
  }

  while (1) {
    const size_t numOperations = operationsCounter.getValue();

    if (numOperations >= (size_t) Operations) {
      break;
    }

    if (Progress && numOperations >= nextReportValue) {
      LOG_INFO("number of operations: %d", (int) nextReportValue);
      nextReportValue += stepValue;
    }

    usleep(20000);
  }

  double time = TRI_microtime() - start;
  double requestTime = 0.0;

  for (int i = 0; i < Concurrency; ++i) {
    requestTime += threads[i]->getTime();
  }

  size_t failures = operationsCounter.failures();

  cout << endl;
  cout << "Total number of operations: " << Operations <<
          ", keep alive: " << (KeepAlive ? "yes" : "no") <<
          ", async: " << (Async ? "yes" : "no")  <<
          ", batch size: " << BatchSize <<
          ", concurrency level (threads): " << Concurrency <<
          endl;

  cout << "Test case: " << TestCase <<
          ", complexity: " << Complexity <<
          ", database: '" << BaseClient.databaseName() <<
          "', collection: '" << Collection << "'" <<
          endl;

  cout << "Total request/response duration (sum of all threads): " << fixed << requestTime << " s" << endl;
  cout << "Request/response duration (per thread): " << fixed << (requestTime / (double) Concurrency) << " s" << endl;
  cout << "Time needed per operation: " << fixed << (time / Operations) << " s" << endl;
  cout << "Time needed per operation per thread: " << fixed << (time / (double) Operations * (double) Concurrency) << " s" << endl;
  cout << "Operations per second rate: " << fixed << ((double) Operations / time) << endl;
  cout << "Elapsed time since start: " << fixed << time << " s" << endl << endl;

  if (failures > 0) {
    cerr << "WARNING: " << failures << " arangob request(s) failed!!" << endl;
  }

  testCase->tearDown();

  for (int i = 0; i < Concurrency; ++i) {
    threads[i]->join();
    delete threads[i];
    delete endpoints[i];
  }

  delete testCase;

  TRIAGENS_REST_SHUTDOWN;

  if (failures > 0) {
    ret = EXIT_FAILURE;
  }

  arangobExitFunction(ret, NULL);

  return ret;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>included correct init header<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief arango benchmark tool
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Basics/Common.h"

#include <stdio.h>

#include "ArangoShell/ArangoClient.h"
#include "Basics/Mutex.h"
#include "Basics/MutexLocker.h"
#include "Basics/ProgramOptions.h"
#include "Basics/ProgramOptionsDescription.h"
#include "Basics/StringUtils.h"
#include "BasicsC/init.h"
#include "BasicsC/logging.h"
#include "BasicsC/random.h"
#include "BasicsC/tri-strings.h"
#include "BasicsC/string-buffer.h"
#include "BasicsC/terminal-utils.h"
#include "Rest/Endpoint.h"
#include "Rest/HttpRequest.h"
#include "Rest/InitialiseRest.h"
#include "SimpleHttpClient/SimpleHttpClient.h"
#include "SimpleHttpClient/SimpleHttpResult.h"
#include "Benchmark/BenchmarkCounter.h"
#include "Benchmark/BenchmarkOperation.h"
#include "Benchmark/BenchmarkThread.h"

using namespace std;
using namespace triagens::basics;
using namespace triagens::httpclient;
using namespace triagens::rest;
using namespace triagens::arango;
using namespace triagens::arangob;

// -----------------------------------------------------------------------------
// --SECTION--                                                 private variables
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Benchmark
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief base class for clients
////////////////////////////////////////////////////////////////////////////////

ArangoClient BaseClient;

////////////////////////////////////////////////////////////////////////////////
/// @brief started counter
////////////////////////////////////////////////////////////////////////////////

static atomic<int> Started;

////////////////////////////////////////////////////////////////////////////////
/// @brief mutex for start counter
////////////////////////////////////////////////////////////////////////////////

Mutex StartMutex;

////////////////////////////////////////////////////////////////////////////////
/// @brief send asychronous requests
////////////////////////////////////////////////////////////////////////////////

static bool Async = false;

////////////////////////////////////////////////////////////////////////////////
/// @brief number of operations in one batch
////////////////////////////////////////////////////////////////////////////////

static int BatchSize = 0;

////////////////////////////////////////////////////////////////////////////////
/// @brief collection to use
////////////////////////////////////////////////////////////////////////////////

static string Collection = "ArangoBenchmark";

////////////////////////////////////////////////////////////////////////////////
/// @brief complexity parameter for tests
////////////////////////////////////////////////////////////////////////////////

static uint64_t Complexity = 1;

////////////////////////////////////////////////////////////////////////////////
/// @brief concurrency
////////////////////////////////////////////////////////////////////////////////

static int Concurrency = 1;

////////////////////////////////////////////////////////////////////////////////
/// @brief use a startup delay
////////////////////////////////////////////////////////////////////////////////

static bool Delay = false;

////////////////////////////////////////////////////////////////////////////////
/// @brief use HTTP keep-alive
////////////////////////////////////////////////////////////////////////////////

static bool KeepAlive = true;

////////////////////////////////////////////////////////////////////////////////
/// @brief number of operations to perform
////////////////////////////////////////////////////////////////////////////////

static int Operations = 1000;

////////////////////////////////////////////////////////////////////////////////
/// @brief display progress
////////////////////////////////////////////////////////////////////////////////

static bool Progress = true;

////////////////////////////////////////////////////////////////////////////////
/// @brief test case to use
////////////////////////////////////////////////////////////////////////////////

static string TestCase = "version";

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief includes all the test cases
////////////////////////////////////////////////////////////////////////////////

#include "Benchmark/test-cases.h"

// -----------------------------------------------------------------------------
// --SECTION--                                                 private functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Benchmark
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief update the number of ready threads. this is a callback function
/// that is called by each thread after it is created
////////////////////////////////////////////////////////////////////////////////

static void UpdateStartCounter () {
  ++Started;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get the value of the number of started threads counter
////////////////////////////////////////////////////////////////////////////////

static int GetStartCounter () {
  return Started;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief print a status line (if ! quiet)
////////////////////////////////////////////////////////////////////////////////

static void Status (const string& value) {
  if (! BaseClient.quiet()) {
    cout << value << endl;
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief parses the program options
////////////////////////////////////////////////////////////////////////////////

static void ParseProgramOptions (int argc, char* argv[]) {
  ProgramOptionsDescription description("STANDARD options");

  description
    ("async", &Async, "send asychronous requests")
    ("concurrency", &Concurrency, "number of parallel connections")
    ("requests", &Operations, "total number of operations")
    ("batch-size", &BatchSize, "number of operations in one batch (0 disables batching)")
    ("keep-alive", &KeepAlive, "use HTTP keep-alive")
    ("collection", &Collection, "collection name to use in tests")
    ("test-case", &TestCase, "test case to use")
    ("complexity", &Complexity, "complexity parameter for the test")
    ("delay", &Delay, "use a startup delay (necessary only when run in series)")
    ("progress", &Progress, "show progress")
  ;

  BaseClient.setupGeneral(description);
  BaseClient.setupServer(description);

  vector<string> arguments;
  description.arguments(&arguments);

  ProgramOptions options;
  BaseClient.parse(options, description, "--concurrency <concurrency> --requests <request> --test-case <case> ...", argc, argv, "arangob.conf");
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                  public functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Benchmark
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief startup and exit functions
////////////////////////////////////////////////////////////////////////////////

static void arangobEntryFunction ();
static void arangobExitFunction (int, void*);

#ifdef _WIN32

// .............................................................................
// Call this function to do various initialisations for windows only
// .............................................................................

void arangobEntryFunction () {
  int maxOpenFiles = 1024;
  int res = 0;

  // ...........................................................................
  // Uncomment this to call this for extended debug information.
  // If you familiar with valgrind ... then this is not like that, however
  // you do get some similar functionality.
  // ...........................................................................
  //res = initialiseWindows(TRI_WIN_INITIAL_SET_DEBUG_FLAG, 0);

  res = initialiseWindows(TRI_WIN_INITIAL_SET_INVALID_HANLE_HANDLER, 0);
  if (res != 0) {
    _exit(1);
  }

  res = initialiseWindows(TRI_WIN_INITIAL_SET_MAX_STD_IO,(const char*)(&maxOpenFiles));
  if (res != 0) {
    _exit(1);
  }

  res = initialiseWindows(TRI_WIN_INITIAL_WSASTARTUP_FUNCTION_CALL, 0);
  if (res != 0) {
    _exit(1);
  }

  TRI_Application_Exit_SetExit(arangobExitFunction);
}

static void arangobExitFunction (int exitCode, void* data) {
  int res = 0;
  // ...........................................................................
  // TODO: need a terminate function for windows to be called and cleanup
  // any windows specific stuff.
  // ...........................................................................

  res = finaliseWindows(TRI_WIN_FINAL_WSASTARTUP_FUNCTION_CALL, 0);

  if (res != 0) {
    exit(1);
  }

  exit(exitCode);
}
#else

static void arangobEntryFunction () {
}

static void arangobExitFunction (int exitCode, void* data) {
}

#endif

////////////////////////////////////////////////////////////////////////////////
/// @brief main
////////////////////////////////////////////////////////////////////////////////

int main (int argc, char* argv[]) {
  int ret = EXIT_SUCCESS;

  arangobEntryFunction();

  TRIAGENS_C_INITIALISE(argc, argv);
  TRIAGENS_REST_INITIALISE(argc, argv);

  TRI_InitialiseLogging(false);

  BaseClient.setEndpointString(Endpoint::getDefaultEndpoint());

  // .............................................................................
  // parse the program options
  // .............................................................................

  ParseProgramOptions(argc, argv);

  // .............................................................................
  // set-up client connection
  // .............................................................................

  BaseClient.createEndpoint();

  if (BaseClient.endpointServer() == 0) {
    LOG_FATAL_AND_EXIT("invalid value for --server.endpoint ('%s')", BaseClient.endpointString().c_str());
  }

  BenchmarkOperation* testCase = GetTestCase(TestCase);

  if (testCase == 0) {
    LOG_FATAL_AND_EXIT("invalid test case name '%s'", TestCase.c_str());
    return EXIT_FAILURE; // will not be reached
  }

  Status("starting threads...");

  BenchmarkCounter<unsigned long> operationsCounter(0, (unsigned long) Operations);
  ConditionVariable startCondition;

  vector<Endpoint*> endpoints;
  vector<BenchmarkThread*> threads;

  const double stepSize = (double) Operations / (double) Concurrency;
  int64_t realStep = (int64_t) stepSize;
  if (stepSize - (double) ((int64_t) stepSize) > 0.0) {
    realStep++;
  }
  if (realStep % 1000 != 0) {
    realStep += 1000 - (realStep % 1000);
  }
  // add some more offset so we don't get into trouble with threads of different speed
  realStep += 10000;

  // start client threads
  for (int i = 0; i < Concurrency; ++i) {
    Endpoint* endpoint = Endpoint::clientFactory(BaseClient.endpointString());
    endpoints.push_back(endpoint);

    BenchmarkThread* thread = new BenchmarkThread(testCase,
        &startCondition,
        &UpdateStartCounter,
        i,
        (unsigned long) BatchSize,
        &operationsCounter,
        endpoint,
        BaseClient.databaseName(),
        BaseClient.username(),
        BaseClient.password(),
        BaseClient.requestTimeout(),
        BaseClient.connectTimeout(),
        BaseClient.sslProtocol(),
        KeepAlive,
        Async);

    threads.push_back(thread);
    thread->setOffset((size_t) (i * realStep));
    thread->start();
  }

  // give all threads a chance to start so they will not miss the broadcast
  while (GetStartCounter() < Concurrency) {
    usleep(5000);
  }

  if (Delay) {
    Status("sleeping (startup delay)...");
    sleep(10);
  }
  Status("executing tests...");

  double start = TRI_microtime();

  // broadcast the start signal to all threads
  {
    ConditionLocker guard(&startCondition);
    guard.broadcast();
  }

  const size_t stepValue = (Operations / 20);
  size_t nextReportValue = stepValue;

  if (nextReportValue < 100) {
    nextReportValue = 100;
  }

  while (1) {
    const size_t numOperations = operationsCounter.getValue();

    if (numOperations >= (size_t) Operations) {
      break;
    }

    if (Progress && numOperations >= nextReportValue) {
      LOG_INFO("number of operations: %d", (int) nextReportValue);
      nextReportValue += stepValue;
    }

    usleep(20000);
  }

  double time = TRI_microtime() - start;
  double requestTime = 0.0;

  for (int i = 0; i < Concurrency; ++i) {
    requestTime += threads[i]->getTime();
  }

  size_t failures = operationsCounter.failures();

  cout << endl;
  cout << "Total number of operations: " << Operations <<
          ", keep alive: " << (KeepAlive ? "yes" : "no") <<
          ", async: " << (Async ? "yes" : "no")  <<
          ", batch size: " << BatchSize <<
          ", concurrency level (threads): " << Concurrency <<
          endl;

  cout << "Test case: " << TestCase <<
          ", complexity: " << Complexity <<
          ", database: '" << BaseClient.databaseName() <<
          "', collection: '" << Collection << "'" <<
          endl;

  cout << "Total request/response duration (sum of all threads): " << fixed << requestTime << " s" << endl;
  cout << "Request/response duration (per thread): " << fixed << (requestTime / (double) Concurrency) << " s" << endl;
  cout << "Time needed per operation: " << fixed << (time / Operations) << " s" << endl;
  cout << "Time needed per operation per thread: " << fixed << (time / (double) Operations * (double) Concurrency) << " s" << endl;
  cout << "Operations per second rate: " << fixed << ((double) Operations / time) << endl;
  cout << "Elapsed time since start: " << fixed << time << " s" << endl << endl;

  if (failures > 0) {
    cerr << "WARNING: " << failures << " arangob request(s) failed!!" << endl;
  }

  testCase->tearDown();

  for (int i = 0; i < Concurrency; ++i) {
    threads[i]->join();
    delete threads[i];
    delete endpoints[i];
  }

  delete testCase;

  TRIAGENS_REST_SHUTDOWN;

  if (failures > 0) {
    ret = EXIT_FAILURE;
  }

  arangobExitFunction(ret, NULL);

  return ret;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<|endoftext|>


<commit_before>/*
 *  Copyright 2010-2011 Fabric Technologies Inc. All rights reserved.
 */

#include "FunctionBuilder.h"
#include "ModuleBuilder.h"
#include "Manager.h"
#include <Fabric/Core/CG/OverloadNames.h>
#include <Fabric/Core/RT/Manager.h>

#include <llvm/Module.h>
#include <llvm/Function.h>
#include <llvm/Analysis/Verifier.h>

namespace Fabric
{
  namespace CG
  {
    FunctionBuilder::FunctionBuilder(
      ModuleBuilder &moduleBuilder,
      std::string const &pencilName,
      std::string const &symbolName,
      RC::ConstHandle<Adapter> const &returnAdapter,
      ParamVector const &params,
      size_t flags,
      size_t cost
      )
      : m_moduleBuilder( moduleBuilder )
      , m_functionScope( NULL )
    {
      build( pencilName, symbolName, returnAdapter, params, flags, cost );
    }

    FunctionBuilder::FunctionBuilder(
      ModuleBuilder &moduleBuilder,
      std::string const &pencilName,
      std::string const &symbolName,
      std::string const &paramLayout,
      size_t flags
      )
      : m_moduleBuilder( moduleBuilder )
      , m_functionScope( NULL )
    {
      RC::Handle<CG::Manager> manager = moduleBuilder.getManager();
      CG::ParamVector paramList;
      RC::ConstHandle<Adapter> returnAdapter;

      if( !paramLayout.empty() )
      {
          // The parameter layout is defined thus "{=,<,>}[Type]:[Name]"
          // E.g.: "=Scalar,<Integer:num,>Integer:tex"
          // corresponds to the following KL function:
          /// Scalar foo( in Integer num, io/out Integer tex );

        size_t          start, end;
        start = 0;

        do
        {
          end = paramLayout.find( ',', start + 1 );

          CG::Usage usage = CG::USAGE_UNSPECIFIED;
          if ( paramLayout[ start ] == '<' )
            usage = CG::USAGE_RVALUE;
          else if ( paramLayout[ start ] == '>' )
            usage = CG::USAGE_LVALUE;
          else if ( paramLayout[ start ] == '=' )
          {
            if ( returnAdapter )
              throw Exception( "Malformed function param layout string. Return type already specified: " + paramLayout );

            std::string rtype = paramLayout.substr( start + 1, end - start - 1 );
            RC::ConstHandle<RT::Desc> typeDesc = manager->getRTManager()->getDesc( rtype );
            returnAdapter = manager->getAdapter( typeDesc );
          }
          else
            throw Exception( "Malformed function param layout string. Missing in/out marker: " + paramLayout.substr( start, end - start ) );

          if ( usage != CG::USAGE_UNSPECIFIED )
          {
            size_t split = paramLayout.find( ' ', start + 2 );
            if ( split > end )
              throw Exception( "Malformed function param layout string. Missing type: " + paramLayout.substr( start, end - start ) );

            std::string ptype = paramLayout.substr( start + 1, split - start - 1 );
            RC::ConstHandle<RT::Desc> typeDesc = manager->getRTManager()->getDesc( ptype );
            RC::ConstHandle<CG::Adapter> typeAdapter = manager->getAdapter( typeDesc );

            std::string pname = paramLayout.substr( split + 1, end - split - 1 );
            if ( pname.empty() )
              throw Exception( "Malformed function param layout string. Missing param name: " + paramLayout.substr( start, end - start ) );

            paramList.push_back( CG::FunctionParam( pname, typeAdapter, usage ) );
          }

          start = end + 1;
        } while( end != std::string::npos );
      }

      build( pencilName, symbolName, returnAdapter, paramList, flags );
    }

    void FunctionBuilder::build(
      std::string const &pencilName,
      std::string const &symbolName,
      RC::ConstHandle<Adapter> const &returnAdapter,
      ParamVector const &params,
      size_t flags,
      size_t cost
      )
    {
      RC::Handle<Context> context = getContext();

      llvm::Type const *llvmReturnType = 0;
      std::vector<llvm::Type const *> llvmParamTypes;

      if ( flags & DirectlyReturnLValue )
      {
        m_haveHiddenReturnLValue = false;
        llvmReturnType = returnAdapter->llvmLType( context );
      }
      else if ( flags & DirectlyReturnRValue )
      {
        m_haveHiddenReturnLValue = false;
        llvmReturnType = returnAdapter->llvmRType( context );
      }
      else if ( returnAdapter )
      {
        if ( returnAdapter->usesReturnLValue() )
        {
          m_haveHiddenReturnLValue = true;
          llvmReturnType = llvm::Type::getVoidTy( context->getLLVMContext() );
          llvmParamTypes.push_back( returnAdapter->llvmLType( context ) );
        }
        else
        {
          m_haveHiddenReturnLValue = false;
          llvmReturnType = returnAdapter->llvmRType( context );
        }
      }
      else
      {
        m_haveHiddenReturnLValue = false;
        llvmReturnType = llvm::Type::getVoidTy( context->getLLVMContext() );
      }

      for ( size_t i=0; i<params.size(); ++i )
        llvmParamTypes.push_back( params[i].getLLVMType( context ) );

      m_llvmFunctionType = llvm::FunctionType::get( llvmReturnType, llvmParamTypes, false );

      llvm::AttributeWithIndex AWI[1];
      AWI[0] = llvm::AttributeWithIndex::get( ~0u, llvm::Attribute::InlineHint );
      llvm::AttrListPtr attrListPtr = llvm::AttrListPtr::get(AWI, 1);

      llvm::Function *existingLLVMFunction = m_moduleBuilder->getFunction( symbolName.c_str() );
      if ( existingLLVMFunction )
      {
        // [pzion 20110825] FIXME: should verify sanity here through asserts on types, attributes
        // and linkage
        m_llvmFunction = existingLLVMFunction;
      }
      else
      {
        m_llvmFunction = llvm::cast<llvm::Function>( m_moduleBuilder->getOrInsertFunction( symbolName.c_str(), m_llvmFunctionType, attrListPtr ) );
        m_llvmFunction->setLinkage( (flags & ExportSymbol)? llvm::GlobalValue::ExternalLinkage: llvm::GlobalValue::PrivateLinkage );
      }

      llvm::Function::arg_iterator ai = m_llvmFunction->arg_begin();

      ReturnInfo returnInfo( ExprType( returnAdapter, (flags & DirectlyReturnLValue)? USAGE_LVALUE: USAGE_RVALUE ) );
      if ( m_haveHiddenReturnLValue )
      {
        ai->setName( "resultLValue" );
        ai->addAttr( llvm::Attribute::NoCapture );
        ai->addAttr( llvm::Attribute::NoAlias );
        ai->addAttr( llvm::Attribute::StructRet );
        returnInfo = ReturnInfo( ExprType( returnAdapter, USAGE_LVALUE ), ai );
        ++ai;
      }

      m_functionScope = new FunctionScope( m_moduleBuilder.getScope(), returnInfo );

      for ( size_t i=0; i<params.size(); ++i, ++ai )
      {
        FunctionParam const &param = params[i];
        ai->setName( param.getName() );
        if ( param.getUsage() == USAGE_LVALUE
          || param.getAdapter()->isPassByReference()  )
        {
          ai->addAttr( llvm::Attribute::NoCapture );
          ai->addAttr( llvm::Attribute::NoAlias );
        }
        m_functionScope->put( param.getName(), ParameterSymbol::Create( CG::ExprValue( param.getExprType(), context, ai ) ) );
      }

      if ( !pencilName.empty() )
        m_pencil = m_moduleBuilder.addFunction( pencilName, Function( m_llvmFunction, returnInfo, params, cost ) );
    }

    FunctionBuilder::FunctionBuilder(
      ModuleBuilder &moduleBuilder,
      llvm::FunctionType const *llvmFunctionType,
      llvm::Function *llvmFunction
      )
      : m_moduleBuilder( moduleBuilder )
      , m_llvmFunctionType( llvmFunctionType )
      , m_llvmFunction( llvmFunction )
      , m_haveHiddenReturnLValue( false )
    {
      ReturnInfo returnInfo( ExprType() );
      m_functionScope = new FunctionScope( m_moduleBuilder.getScope(), returnInfo );
    }

    ModuleBuilder &FunctionBuilder::getModuleBuilder()
    {
      return m_moduleBuilder;
    }

    RC::Handle<Manager> FunctionBuilder::getManager()
    {
      return m_moduleBuilder.getManager();
    }

    RC::Handle<Context> FunctionBuilder::getContext()
    {
      return m_moduleBuilder.getContext();
    }

    llvm::Function *FunctionBuilder::operator ->()
    {
      return m_llvmFunction;
    }

    llvm::Function *FunctionBuilder::getLLVMFunction()
    {
      return m_llvmFunction;
    }

    FunctionBuilder::~FunctionBuilder()
    {
      delete m_functionScope;
    }

    llvm::Argument *FunctionBuilder::operator[]( size_t index )
    {
      llvm::Function::ArgumentListType &argumentList = m_llvmFunction->getArgumentList();
      llvm::Function::ArgumentListType::iterator it = argumentList.begin();

      // Skip the 'hidden' return value.
      if ( m_haveHiddenReturnLValue )
        ++it;

      while ( index-- )
        ++it;
      return it;
    }

    llvm::BasicBlock *FunctionBuilder::createBasicBlock( std::string const &name )
    {
      return llvm::BasicBlock::Create( getContext()->getLLVMContext(), name, m_llvmFunction );
    }

    FunctionScope &FunctionBuilder::getScope()
    {
      FABRIC_ASSERT( m_functionScope );
      return *m_functionScope;
    }

    RC::ConstHandle<Adapter> FunctionBuilder::maybeGetAdapter( std::string const &userName ) const
    {
      return m_moduleBuilder.maybeGetAdapter( userName );
    }

    RC::ConstHandle<Adapter> FunctionBuilder::getAdapter( std::string const &userName, CG::Location const &location ) const
    {
      return m_moduleBuilder.getAdapter( userName, location );
    }

    FunctionBuilder::FunctionBuilder(
      ModuleBuilder &moduleBuilder,
      RC::ConstHandle<CG::Adapter> const &returnAdapter,
      std::string const &functionName,
      std::string const &param1Name,
      RC::ConstHandle<CG::Adapter> const &param1Adapter,
      Usage param1Usage,
      size_t flags
      )
      : m_moduleBuilder( moduleBuilder )
      , m_functionScope( NULL )
    {
      ParamVector params;
      params.push_back( FriendlyFunctionParam( param1Name, param1Adapter, param1Usage ) );
      std::string pencilName = FunctionPencilName( functionName );
      std::string symbolName = FunctionDefaultSymbolName( functionName, params.getTypes() );
      build( pencilName, symbolName, returnAdapter, params, flags );
      getModuleBuilder().getScope().put( functionName, getPencil() );
    }

    FunctionBuilder::FunctionBuilder(
      ModuleBuilder &moduleBuilder,
      RC::ConstHandle<CG::Adapter> const &returnAdapter,
      std::string const &functionName,
      std::string const &param1Name,
      RC::ConstHandle<CG::Adapter> const &param1Adapter,
      Usage param1Usage,
      std::string const &param2Name,
      RC::ConstHandle<CG::Adapter> const &param2Adapter,
      Usage param2Usage,
      size_t flags
      )
      : m_moduleBuilder( moduleBuilder )
      , m_functionScope( NULL )
    {
      ParamVector params;
      params.push_back( FriendlyFunctionParam( param1Name, param1Adapter, param1Usage ) );
      params.push_back( FriendlyFunctionParam( param2Name, param2Adapter, param2Usage ) );
      std::string pencilName = FunctionPencilName( functionName );
      std::string symbolName = FunctionDefaultSymbolName( functionName, params.getTypes() );
      build( pencilName, symbolName, returnAdapter, params, flags );
      getModuleBuilder().getScope().put( functionName, getPencil() );
    }

    RC::ConstHandle<PencilSymbol> FunctionBuilder::getPencil() const
    {
      return m_pencil;
    }
  }
}
<commit_msg>Accidentally checked in wrong FunctionBuilder, fixing.<commit_after>/*
 *  Copyright 2010-2011 Fabric Technologies Inc. All rights reserved.
 */

#include "FunctionBuilder.h"
#include "ModuleBuilder.h"
#include "Manager.h"
#include <Fabric/Core/CG/OverloadNames.h>
#include <Fabric/Core/RT/Manager.h>

#include <llvm/Module.h>
#include <llvm/Function.h>
#include <llvm/Analysis/Verifier.h>

namespace Fabric
{
  namespace CG
  {
    FunctionBuilder::FunctionBuilder(
      ModuleBuilder &moduleBuilder,
      std::string const &pencilName,
      std::string const &symbolName,
      RC::ConstHandle<Adapter> const &returnAdapter,
      ParamVector const &params,
      size_t flags,
      size_t cost
      )
      : m_moduleBuilder( moduleBuilder )
      , m_functionScope( NULL )
    {
      build( pencilName, symbolName, returnAdapter, params, flags, cost );
    }

    FunctionBuilder::FunctionBuilder(
      ModuleBuilder &moduleBuilder,
      std::string const &pencilName,
      std::string const &symbolName,
      std::string const &paramLayout,
      size_t flags
      )
      : m_moduleBuilder( moduleBuilder )
      , m_functionScope( NULL )
    {
      RC::Handle<CG::Manager> manager = moduleBuilder.getManager();
      CG::ParamVector paramList;
      RC::ConstHandle<Adapter> returnAdapter;

      if( !paramLayout.empty() )
      {
          // The parameter layout is defined thus "{=,<,>}[Type]:[Name]"
          // E.g.: "=Scalar,<Integer:num,>Integer:tex"
          // corresponds to the following KL function:
          /// Scalar foo( in Integer num, io/out Integer tex );

        size_t          start, end;
        start = 0;

        do
        {
          end = paramLayout.find( ',', start + 1 );

          CG::Usage usage = CG::USAGE_UNSPECIFIED;
          if ( paramLayout[ start ] == '<' )
            usage = CG::USAGE_RVALUE;
          else if ( paramLayout[ start ] == '>' )
            usage = CG::USAGE_LVALUE;
          else if ( paramLayout[ start ] == '=' )
          {
            if ( returnAdapter )
              throw Exception( "Malformed function param layout string. Return type already specified: " + paramLayout );

            std::string rtype = paramLayout.substr( start + 1, end - start - 1 );
            RC::ConstHandle<RT::Desc> typeDesc = manager->getRTManager()->getDesc( rtype );
            returnAdapter = manager->getAdapter( typeDesc );
          }
          else
            throw Exception( "Malformed function param layout string. Missing in/out marker: " + paramLayout.substr( start, end - start ) );

          if ( usage != CG::USAGE_UNSPECIFIED )
          {
            size_t split = paramLayout.find( ' ', start + 2 );
            if ( split > end )
              throw Exception( "Malformed function param layout string. Missing type: " + paramLayout.substr( start, end - start ) );

            std::string ptype = paramLayout.substr( start + 1, split - start - 1 );
            RC::ConstHandle<RT::Desc> typeDesc = manager->getRTManager()->getDesc( ptype );
            RC::ConstHandle<CG::Adapter> typeAdapter = manager->getAdapter( typeDesc );

            std::string pname = paramLayout.substr( split + 1, end - split - 1 );
            if ( pname.empty() )
              throw Exception( "Malformed function param layout string. Missing param name: " + paramLayout.substr( start, end - start ) );

            paramList.push_back( CG::FunctionParam( pname, typeAdapter, usage ) );
          }

          start = end + 1;
        } while( end != std::string::npos );
      }

      build( pencilName, symbolName, returnAdapter, paramList, flags );
    }

    void FunctionBuilder::build(
      std::string const &pencilName,
      std::string const &symbolName,
      RC::ConstHandle<Adapter> const &returnAdapter,
      ParamVector const &params,
      size_t flags,
      size_t cost
      )
    {
      RC::Handle<Context> context = getContext();

      llvm::Type const *llvmReturnType = 0;
      std::vector<llvm::Type const *> llvmParamTypes;

      if ( flags & DirectlyReturnLValue )
      {
        m_haveHiddenReturnLValue = false;
        llvmReturnType = returnAdapter->llvmLType( context );
      }
      else if ( flags & DirectlyReturnRValue )
      {
        m_haveHiddenReturnLValue = false;
        llvmReturnType = returnAdapter->llvmRType( context );
      }
      else if ( returnAdapter )
      {
        if ( returnAdapter->usesReturnLValue() )
        {
          m_haveHiddenReturnLValue = true;
          llvmReturnType = llvm::Type::getVoidTy( context->getLLVMContext() );
          llvmParamTypes.push_back( returnAdapter->llvmLType( context ) );
        }
        else
        {
          m_haveHiddenReturnLValue = false;
          llvmReturnType = returnAdapter->llvmRType( context );
        }
      }
      else
      {
        m_haveHiddenReturnLValue = false;
        llvmReturnType = llvm::Type::getVoidTy( context->getLLVMContext() );
      }

      for ( size_t i=0; i<params.size(); ++i )
        llvmParamTypes.push_back( params[i].getLLVMType( context ) );

      m_llvmFunctionType = llvm::FunctionType::get( llvmReturnType, llvmParamTypes, false );

      llvm::AttributeWithIndex AWI[1];
      AWI[0] = llvm::AttributeWithIndex::get( ~0u, llvm::Attribute::InlineHint );
      llvm::AttrListPtr attrListPtr = llvm::AttrListPtr::get(AWI, 1);

      llvm::Function *existingLLVMFunction = m_moduleBuilder->getFunction( symbolName.c_str() );
      if ( existingLLVMFunction )
      {
        // [pzion 20110825] FIXME: should verify sanity here through asserts on types, attributes
        // and linkage
        m_llvmFunction = existingLLVMFunction;
      }
      else
      {
        m_llvmFunction = llvm::cast<llvm::Function>( m_moduleBuilder->getOrInsertFunction( symbolName.c_str(), m_llvmFunctionType, attrListPtr ) );
        m_llvmFunction->setLinkage( (flags & ExportSymbol)? llvm::GlobalValue::ExternalLinkage: llvm::GlobalValue::PrivateLinkage );
      }

      llvm::Function::arg_iterator ai = m_llvmFunction->arg_begin();

      ReturnInfo returnInfo( ExprType( returnAdapter, (flags & DirectlyReturnLValue)? USAGE_LVALUE: USAGE_RVALUE ) );
      if ( m_haveHiddenReturnLValue )
      {
        ai->setName( "resultLValue" );
        ai->addAttr( llvm::Attribute::NoCapture );
        ai->addAttr( llvm::Attribute::NoAlias );
        ai->addAttr( llvm::Attribute::StructRet );
        returnInfo = ReturnInfo( ExprType( returnAdapter, USAGE_LVALUE ), ai );
        ++ai;
      }

      m_functionScope = new FunctionScope( m_moduleBuilder.getScope(), returnInfo );

      for ( size_t i=0; i<params.size(); ++i, ++ai )
      {
        FunctionParam const &param = params[i];
        ai->setName( param.getName() );
        if ( param.getUsage() == USAGE_LVALUE
          || param.getAdapter()->isPassByReference()  )
        {
          ai->addAttr( llvm::Attribute::NoCapture );
          ai->addAttr( llvm::Attribute::NoAlias );
        }
        m_functionScope->put( param.getName(), ParameterSymbol::Create( CG::ExprValue( param.getExprType(), context, ai ) ) );
      }

      if ( !pencilName.empty() )
        m_pencil = m_moduleBuilder.addFunction( pencilName, Function( m_llvmFunction, returnInfo, params, cost ) );
    }

    FunctionBuilder::FunctionBuilder(
      ModuleBuilder &moduleBuilder,
      llvm::FunctionType const *llvmFunctionType,
      llvm::Function *llvmFunction
      )
      : m_moduleBuilder( moduleBuilder )
      , m_llvmFunctionType( llvmFunctionType )
      , m_llvmFunction( llvmFunction )
      , m_haveHiddenReturnLValue( false )
    {
      ReturnInfo returnInfo( ExprType(), 0 );
      m_functionScope = new FunctionScope( m_moduleBuilder.getScope(), returnInfo );
    }

    ModuleBuilder &FunctionBuilder::getModuleBuilder()
    {
      return m_moduleBuilder;
    }

    RC::Handle<Manager> FunctionBuilder::getManager()
    {
      return m_moduleBuilder.getManager();
    }

    RC::Handle<Context> FunctionBuilder::getContext()
    {
      return m_moduleBuilder.getContext();
    }

    llvm::Function *FunctionBuilder::operator ->()
    {
      return m_llvmFunction;
    }

    llvm::Function *FunctionBuilder::getLLVMFunction()
    {
      return m_llvmFunction;
    }

    FunctionBuilder::~FunctionBuilder()
    {
      delete m_functionScope;
    }

    llvm::Argument *FunctionBuilder::operator[]( size_t index )
    {
      llvm::Function::ArgumentListType &argumentList = m_llvmFunction->getArgumentList();
      llvm::Function::ArgumentListType::iterator it = argumentList.begin();

      // Skip the 'hidden' return value.
      if ( m_haveHiddenReturnLValue )
        ++it;

      while ( index-- )
        ++it;
      return it;
    }

    llvm::BasicBlock *FunctionBuilder::createBasicBlock( std::string const &name )
    {
      return llvm::BasicBlock::Create( getContext()->getLLVMContext(), name, m_llvmFunction );
    }

    FunctionScope &FunctionBuilder::getScope()
    {
      FABRIC_ASSERT( m_functionScope );
      return *m_functionScope;
    }

    RC::ConstHandle<Adapter> FunctionBuilder::maybeGetAdapter( std::string const &userName ) const
    {
      return m_moduleBuilder.maybeGetAdapter( userName );
    }

    RC::ConstHandle<Adapter> FunctionBuilder::getAdapter( std::string const &userName, CG::Location const &location ) const
    {
      return m_moduleBuilder.getAdapter( userName, location );
    }

    FunctionBuilder::FunctionBuilder(
      ModuleBuilder &moduleBuilder,
      RC::ConstHandle<CG::Adapter> const &returnAdapter,
      std::string const &functionName,
      std::string const &param1Name,
      RC::ConstHandle<CG::Adapter> const &param1Adapter,
      Usage param1Usage,
      size_t flags
      )
      : m_moduleBuilder( moduleBuilder )
      , m_functionScope( NULL )
    {
      ParamVector params;
      params.push_back( FriendlyFunctionParam( param1Name, param1Adapter, param1Usage ) );
      std::string pencilName = FunctionPencilName( functionName );
      std::string symbolName = FunctionDefaultSymbolName( functionName, params.getTypes() );
      build( pencilName, symbolName, returnAdapter, params, flags );
      getModuleBuilder().getScope().put( functionName, getPencil() );
    }

    FunctionBuilder::FunctionBuilder(
      ModuleBuilder &moduleBuilder,
      RC::ConstHandle<CG::Adapter> const &returnAdapter,
      std::string const &functionName,
      std::string const &param1Name,
      RC::ConstHandle<CG::Adapter> const &param1Adapter,
      Usage param1Usage,
      std::string const &param2Name,
      RC::ConstHandle<CG::Adapter> const &param2Adapter,
      Usage param2Usage,
      size_t flags
      )
      : m_moduleBuilder( moduleBuilder )
      , m_functionScope( NULL )
    {
      ParamVector params;
      params.push_back( FriendlyFunctionParam( param1Name, param1Adapter, param1Usage ) );
      params.push_back( FriendlyFunctionParam( param2Name, param2Adapter, param2Usage ) );
      std::string pencilName = FunctionPencilName( functionName );
      std::string symbolName = FunctionDefaultSymbolName( functionName, params.getTypes() );
      build( pencilName, symbolName, returnAdapter, params, flags );
      getModuleBuilder().getScope().put( functionName, getPencil() );
    }

    RC::ConstHandle<PencilSymbol> FunctionBuilder::getPencil() const
    {
      return m_pencil;
    }
  }
}
<|endoftext|>


<commit_before>// Time:  O(nlogn)
// Space: O(n)

class Solution {
public:
    /**
     * @param A an integer array
     * @param start an integer
     * @param end an integer
     * @return the number of possible answer
     */
    int subarraySumII(vector<int>& A, int start, int end) {
        // sum_from_start[i] denotes sum for 0 ~ i - 1.
        vector<int> sum_from_start(A.size() + 1);
        partial_sum(A.begin(), A.end(), sum_from_start.begin() + 1);

        int result = 0;
        for (int i = 0, j = 0; j < A.size(); ++j) {
            if (sum_from_start[j + 1] >= start) {
                auto l = lower_bound(sum_from_start.begin(), sum_from_start.begin() + j + 1,
                                     sum_from_start[j + 1] - end);
                auto r = upper_bound(sum_from_start.begin(), sum_from_start.begin() + j + 1,
                                     sum_from_start[j + 1] - start);
                if (l != sum_from_start.begin() + j + 1) {
                    result += (r - sum_from_start.begin()) - (l - sum_from_start.begin());
                }
            }
        }

        return result;
    }
};

// Time:  O(n^2)
// Space: O(n)
class Solution2 {
public:
    /**
     * @param A an integer array
     * @param start an integer
     * @param end an integer
     * @return the number of possible answer
     */
    int subarraySumII(vector<int>& A, int start, int end) {
        // sum_from_start[i] denotes sum for 0 ~ i - 1.
        vector<int> sum_from_start(A.size() + 1);
        partial_sum(A.begin(), A.end(), sum_from_start.begin() + 1);

        int result = 0;
        for (int i = 0, j = 0; j < A.size(); ++j) {
            int k = i;
            while (k <= j) {
                if (sum_from_start[j + 1] - sum_from_start[k] >= start &&
                    sum_from_start[j + 1] - sum_from_start[k] <= end) {
                    ++result;
                }
                ++k;
            }
        }

        return result;
    }
};
<commit_msg>Update subarray-sum-ii.cpp<commit_after>// Time:  O(nlogn)
// Space: O(n)

class Solution {
public:
    /**
     * @param A an integer array
     * @param start an integer
     * @param end an integer
     * @return the number of possible answer
     */
    int subarraySumII(vector<int>& A, int start, int end) {
        // sum_from_start[i] denotes sum for 0 ~ i - 1.
        vector<int> sum_from_start(A.size() + 1);
        partial_sum(A.begin(), A.end(), sum_from_start.begin() + 1);

        int result = 0;
        for (int i = 0, j = 0; j < A.size(); ++j) {
            auto l = lower_bound(sum_from_start.begin(), sum_from_start.begin() + j + 1,
                                 sum_from_start[j + 1] - end);
            auto r = upper_bound(sum_from_start.begin(), sum_from_start.begin() + j + 1,
                                 sum_from_start[j + 1] - start);
            result += (r - sum_from_start.begin()) - (l - sum_from_start.begin());
        }

        return result;
    }
};

// Time:  O(n^2)
// Space: O(n)
class Solution2 {
public:
    /**
     * @param A an integer array
     * @param start an integer
     * @param end an integer
     * @return the number of possible answer
     */
    int subarraySumII(vector<int>& A, int start, int end) {
        // sum_from_start[i] denotes sum for 0 ~ i - 1.
        vector<int> sum_from_start(A.size() + 1);
        partial_sum(A.begin(), A.end(), sum_from_start.begin() + 1);

        int result = 0;
        for (int i = 0, j = 0; j < A.size(); ++j) {
            int k = i;
            while (k <= j) {
                if (sum_from_start[j + 1] - sum_from_start[k] >= start &&
                    sum_from_start[j + 1] - sum_from_start[k] <= end) {
                    ++result;
                }
                ++k;
            }
        }

        return result;
    }
};
<|endoftext|>


<commit_before>#include "ScalarType.h"
#include "Utils.h"
#include <cassert>

ScalarType::ScalarType()
{
}

ScalarType::ScalarType(double value)
:value(value)
{
}

ScalarType::ScalarType(double value, double tb)
:value(value)
,tiebreaker(tiebreaker)
{
	assert(tiebreaker > 0. && tiebreaker < 1.);
}

void ScalarType::from_prior(RNG& rng)
{
	tiebreaker = rng.rand();
}

double ScalarType::perturb(RNG& rng)
{
	tiebreaker += rng.randh();
	wrap(tiebreaker, 0., 1.);
	return 0.;
}

bool operator < (const ScalarType& s1, const ScalarType& s2)
{
	bool result = false;
	if(s1.value < s2.value)
		result = true;
	else if(s1.value == s2.value && s1.tiebreaker < s2.tiebreaker)
		result = true;
	return result;
}

bool operator <= (const ScalarType& s1, const ScalarType& s2)
{
	bool result = false;
	if(s1.value < s2.value)
		result = true;
	else if(s1.value == s2.value && s1.tiebreaker <= s2.tiebreaker)
		result = true;
	return result;
}

<commit_msg>Fixed bug<commit_after>#include "ScalarType.h"
#include "Utils.h"
#include <cassert>

ScalarType::ScalarType()
{
}

ScalarType::ScalarType(double value)
:value(value)
{
}

ScalarType::ScalarType(double value, double tb)
:value(value)
,tiebreaker(tb)
{
	assert(tiebreaker > 0. && tiebreaker < 1.);
}

void ScalarType::from_prior(RNG& rng)
{
	tiebreaker = rng.rand();
}

double ScalarType::perturb(RNG& rng)
{
	tiebreaker += rng.randh();
	wrap(tiebreaker, 0., 1.);
	return 0.;
}

bool operator < (const ScalarType& s1, const ScalarType& s2)
{
	bool result = false;
	if(s1.value < s2.value)
		result = true;
	else if(s1.value == s2.value && s1.tiebreaker < s2.tiebreaker)
		result = true;
	return result;
}

bool operator <= (const ScalarType& s1, const ScalarType& s2)
{
	bool result = false;
	if(s1.value < s2.value)
		result = true;
	else if(s1.value == s2.value && s1.tiebreaker <= s2.tiebreaker)
		result = true;
	return result;
}

<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "chrome/browser/chromeos/login/authenticator.h"
#include "chrome/browser/chromeos/login/screen_observer.h"
#include "chrome/browser/policy/auto_enrollment_client.h"
#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/browser/policy/cloud_policy_data_store.h"
#include "chrome/browser/policy/enterprise_metrics.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"

namespace chromeos {

namespace {

// Retry for InstallAttrs initialization every 500ms.
const int kLockRetryIntervalMs = 500;

}  // namespace

EnterpriseEnrollmentScreen::EnterpriseEnrollmentScreen(
    ScreenObserver* observer,
    EnterpriseEnrollmentScreenActor* actor)
    : WizardScreen(observer),
      actor_(actor),
      is_auto_enrollment_(false),
      is_showing_(false),
      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
  actor_->SetController(this);
  // Init the TPM if it has not been done until now (in debug build we might
  // have not done that yet).
  chromeos::CryptohomeLibrary* cryptohome =
      chromeos::CrosLibrary::Get()->GetCryptohomeLibrary();
  if (cryptohome &&
      cryptohome->TpmIsEnabled() &&
      !cryptohome->TpmIsBeingOwned() &&
      !cryptohome->TpmIsOwned()) {
    cryptohome->TpmCanAttemptOwnership();
  }
}

EnterpriseEnrollmentScreen::~EnterpriseEnrollmentScreen() {}

void EnterpriseEnrollmentScreen::SetParameters(bool is_auto_enrollment,
                                               const std::string& user) {
  is_auto_enrollment_ = is_auto_enrollment;
  user_ = user.empty() ? user : Authenticator::Canonicalize(user);
}

void EnterpriseEnrollmentScreen::PrepareToShow() {
  actor_->PrepareToShow();
}

void EnterpriseEnrollmentScreen::Show() {
  is_showing_ = true;
  actor_->Show();
}

void EnterpriseEnrollmentScreen::Hide() {
  is_showing_ = false;
  actor_->Hide();
}

void EnterpriseEnrollmentScreen::OnOAuthTokenAvailable(
    const std::string& user,
    const std::string& token) {
  user_ = Authenticator::Canonicalize(user);
  RegisterForDevicePolicy(token);
}

void EnterpriseEnrollmentScreen::OnConfirmationClosed(bool go_back_to_signin) {
  // If the machine has been put in KIOSK mode we have to restart the session
  // here to go in the proper KIOSK mode login screen.
  policy::BrowserPolicyConnector* policy_connector =
      g_browser_process->browser_policy_connector();
  if (policy_connector && policy_connector->GetDeviceCloudPolicyDataStore() &&
      policy_connector->GetDeviceCloudPolicyDataStore()->device_mode() ==
          policy::DEVICE_MODE_KIOSK) {
    DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
    return;
  }

  get_screen_observer()->OnExit(go_back_to_signin ?
      ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED :
      ScreenObserver::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED);
}

bool EnterpriseEnrollmentScreen::IsAutoEnrollment(std::string* user) {
  if (is_auto_enrollment_)
    *user = user_;
  return is_auto_enrollment_;
}

void EnterpriseEnrollmentScreen::OnPolicyStateChanged(
    policy::CloudPolicySubsystem::PolicySubsystemState state,
    policy::CloudPolicySubsystem::ErrorDetails error_details) {

  if (is_showing_) {
    switch (state) {
      case policy::CloudPolicySubsystem::UNENROLLED:
        switch (error_details) {
          case policy::CloudPolicySubsystem::BAD_SERIAL_NUMBER:
            actor_->ShowSerialNumberError();
            break;
          case policy::CloudPolicySubsystem::BAD_ENROLLMENT_MODE:
            actor_->ShowEnrollmentModeError();
            break;
          default:  // Still working...
            return;
        }
        break;
      case policy::CloudPolicySubsystem::BAD_GAIA_TOKEN:
      case policy::CloudPolicySubsystem::LOCAL_ERROR:
        actor_->ShowFatalEnrollmentError();
        break;
      case policy::CloudPolicySubsystem::UNMANAGED:
        actor_->ShowAccountError();
        break;
      case policy::CloudPolicySubsystem::NETWORK_ERROR:
        actor_->ShowNetworkEnrollmentError();
        break;
      case policy::CloudPolicySubsystem::TOKEN_FETCHED:
        if (!is_auto_enrollment_ ||
            g_browser_process->browser_policy_connector()->
                GetDeviceCloudPolicyDataStore()->device_mode() ==
            policy::DEVICE_MODE_ENTERPRISE) {
          WriteInstallAttributesData();
          return;
        } else {
          LOG(ERROR) << "Enrollment can not proceed because Auto-enrollment is "
                     << "not supported for non-enterprise enrollment modes.";
          policy::AutoEnrollmentClient::CancelAutoEnrollment();
          is_auto_enrollment_ = false;
          actor_->ShowAutoEnrollmentError();
          // Set the error state to something distinguishable in the logs.
          state = policy::CloudPolicySubsystem::LOCAL_ERROR;
          error_details = policy::CloudPolicySubsystem::AUTO_ENROLLMENT_ERROR;
        }
        break;
      case policy::CloudPolicySubsystem::SUCCESS:
        // Success!
        registrar_.reset();
        actor_->ShowConfirmationScreen();
        return;
    }
    // We have an error.
    if (!is_auto_enrollment_) {
      UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment,
                                policy::kMetricEnrollmentPolicyFailed,
                                policy::kMetricEnrollmentSize);
    }
    LOG(WARNING) << "Policy subsystem error during enrollment: " << state
                 << " details: " << error_details;
  }

  // Stop the policy infrastructure.
  registrar_.reset();
  g_browser_process->browser_policy_connector()->ResetDevicePolicy();
}

void EnterpriseEnrollmentScreen::WriteInstallAttributesData() {
  // Since this method is also called directly.
  weak_ptr_factory_.InvalidateWeakPtrs();

  switch (g_browser_process->browser_policy_connector()->LockDevice(user_)) {
    case policy::EnterpriseInstallAttributes::LOCK_SUCCESS: {
      // Proceed with policy fetch.
      policy::BrowserPolicyConnector* connector =
          g_browser_process->browser_policy_connector();
      connector->FetchCloudPolicy();
      return;
    }
    case policy::EnterpriseInstallAttributes::LOCK_NOT_READY: {
      // InstallAttributes not ready yet, retry later.
      LOG(WARNING) << "Install Attributes not ready yet will retry in "
                   << kLockRetryIntervalMs << "ms.";
      MessageLoop::current()->PostDelayedTask(
          FROM_HERE,
          base::Bind(&EnterpriseEnrollmentScreen::WriteInstallAttributesData,
                     weak_ptr_factory_.GetWeakPtr()),
          kLockRetryIntervalMs);
      return;
    }
    case policy::EnterpriseInstallAttributes::LOCK_BACKEND_ERROR: {
      actor_->ShowFatalEnrollmentError();
      return;
    }
    case policy::EnterpriseInstallAttributes::LOCK_WRONG_USER: {
      LOG(ERROR) << "Enrollment can not proceed because the InstallAttrs "
                 << "has been locked already!";
      actor_->ShowFatalEnrollmentError();
      return;
    }
  }

  NOTREACHED();
}

void EnterpriseEnrollmentScreen::RegisterForDevicePolicy(
    const std::string& token) {
  policy::BrowserPolicyConnector* connector =
      g_browser_process->browser_policy_connector();
  if (!connector->device_cloud_policy_subsystem()) {
    LOG(ERROR) << "Cloud policy subsystem not initialized.";
  } else if (connector->IsEnterpriseManaged()) {
    LOG(ERROR) << "Device is already enterprise managed!";
  } else if (connector->device_cloud_policy_subsystem()->state() ==
      policy::CloudPolicySubsystem::SUCCESS) {
    LOG(ERROR) << "A previous enrollment already succeeded!";
  } else {
    // Make sure the device policy subsystem is in a clean slate.
    connector->ResetDevicePolicy();
    connector->ScheduleServiceInitialization(0);
    registrar_.reset(new policy::CloudPolicySubsystem::ObserverRegistrar(
        connector->device_cloud_policy_subsystem(), this));
    // Push the credentials to the policy infrastructure. It'll start enrollment
    // and notify us of progress through CloudPolicySubsystem::Observer.
    connector->RegisterForDevicePolicy(user_, token, is_auto_enrollment_);
    return;
  }
  NOTREACHED();
  if (is_showing_)
    actor_->ShowFatalEnrollmentError();
}

}  // namespace chromeos
<commit_msg>Update uses of TimeDelta in enrollment screen code.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_screen.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "chrome/browser/chromeos/login/authenticator.h"
#include "chrome/browser/chromeos/login/screen_observer.h"
#include "chrome/browser/policy/auto_enrollment_client.h"
#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/browser/policy/cloud_policy_data_store.h"
#include "chrome/browser/policy/enterprise_metrics.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"

namespace chromeos {

namespace {

// Retry for InstallAttrs initialization every 500ms.
const int kLockRetryIntervalMs = 500;

}  // namespace

EnterpriseEnrollmentScreen::EnterpriseEnrollmentScreen(
    ScreenObserver* observer,
    EnterpriseEnrollmentScreenActor* actor)
    : WizardScreen(observer),
      actor_(actor),
      is_auto_enrollment_(false),
      is_showing_(false),
      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
  actor_->SetController(this);
  // Init the TPM if it has not been done until now (in debug build we might
  // have not done that yet).
  chromeos::CryptohomeLibrary* cryptohome =
      chromeos::CrosLibrary::Get()->GetCryptohomeLibrary();
  if (cryptohome &&
      cryptohome->TpmIsEnabled() &&
      !cryptohome->TpmIsBeingOwned() &&
      !cryptohome->TpmIsOwned()) {
    cryptohome->TpmCanAttemptOwnership();
  }
}

EnterpriseEnrollmentScreen::~EnterpriseEnrollmentScreen() {}

void EnterpriseEnrollmentScreen::SetParameters(bool is_auto_enrollment,
                                               const std::string& user) {
  is_auto_enrollment_ = is_auto_enrollment;
  user_ = user.empty() ? user : Authenticator::Canonicalize(user);
}

void EnterpriseEnrollmentScreen::PrepareToShow() {
  actor_->PrepareToShow();
}

void EnterpriseEnrollmentScreen::Show() {
  is_showing_ = true;
  actor_->Show();
}

void EnterpriseEnrollmentScreen::Hide() {
  is_showing_ = false;
  actor_->Hide();
}

void EnterpriseEnrollmentScreen::OnOAuthTokenAvailable(
    const std::string& user,
    const std::string& token) {
  user_ = Authenticator::Canonicalize(user);
  RegisterForDevicePolicy(token);
}

void EnterpriseEnrollmentScreen::OnConfirmationClosed(bool go_back_to_signin) {
  // If the machine has been put in KIOSK mode we have to restart the session
  // here to go in the proper KIOSK mode login screen.
  policy::BrowserPolicyConnector* policy_connector =
      g_browser_process->browser_policy_connector();
  if (policy_connector && policy_connector->GetDeviceCloudPolicyDataStore() &&
      policy_connector->GetDeviceCloudPolicyDataStore()->device_mode() ==
          policy::DEVICE_MODE_KIOSK) {
    DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
    return;
  }

  get_screen_observer()->OnExit(go_back_to_signin ?
      ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED :
      ScreenObserver::ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED);
}

bool EnterpriseEnrollmentScreen::IsAutoEnrollment(std::string* user) {
  if (is_auto_enrollment_)
    *user = user_;
  return is_auto_enrollment_;
}

void EnterpriseEnrollmentScreen::OnPolicyStateChanged(
    policy::CloudPolicySubsystem::PolicySubsystemState state,
    policy::CloudPolicySubsystem::ErrorDetails error_details) {

  if (is_showing_) {
    switch (state) {
      case policy::CloudPolicySubsystem::UNENROLLED:
        switch (error_details) {
          case policy::CloudPolicySubsystem::BAD_SERIAL_NUMBER:
            actor_->ShowSerialNumberError();
            break;
          case policy::CloudPolicySubsystem::BAD_ENROLLMENT_MODE:
            actor_->ShowEnrollmentModeError();
            break;
          default:  // Still working...
            return;
        }
        break;
      case policy::CloudPolicySubsystem::BAD_GAIA_TOKEN:
      case policy::CloudPolicySubsystem::LOCAL_ERROR:
        actor_->ShowFatalEnrollmentError();
        break;
      case policy::CloudPolicySubsystem::UNMANAGED:
        actor_->ShowAccountError();
        break;
      case policy::CloudPolicySubsystem::NETWORK_ERROR:
        actor_->ShowNetworkEnrollmentError();
        break;
      case policy::CloudPolicySubsystem::TOKEN_FETCHED:
        if (!is_auto_enrollment_ ||
            g_browser_process->browser_policy_connector()->
                GetDeviceCloudPolicyDataStore()->device_mode() ==
            policy::DEVICE_MODE_ENTERPRISE) {
          WriteInstallAttributesData();
          return;
        } else {
          LOG(ERROR) << "Enrollment can not proceed because Auto-enrollment is "
                     << "not supported for non-enterprise enrollment modes.";
          policy::AutoEnrollmentClient::CancelAutoEnrollment();
          is_auto_enrollment_ = false;
          actor_->ShowAutoEnrollmentError();
          // Set the error state to something distinguishable in the logs.
          state = policy::CloudPolicySubsystem::LOCAL_ERROR;
          error_details = policy::CloudPolicySubsystem::AUTO_ENROLLMENT_ERROR;
        }
        break;
      case policy::CloudPolicySubsystem::SUCCESS:
        // Success!
        registrar_.reset();
        actor_->ShowConfirmationScreen();
        return;
    }
    // We have an error.
    if (!is_auto_enrollment_) {
      UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment,
                                policy::kMetricEnrollmentPolicyFailed,
                                policy::kMetricEnrollmentSize);
    }
    LOG(WARNING) << "Policy subsystem error during enrollment: " << state
                 << " details: " << error_details;
  }

  // Stop the policy infrastructure.
  registrar_.reset();
  g_browser_process->browser_policy_connector()->ResetDevicePolicy();
}

void EnterpriseEnrollmentScreen::WriteInstallAttributesData() {
  // Since this method is also called directly.
  weak_ptr_factory_.InvalidateWeakPtrs();

  switch (g_browser_process->browser_policy_connector()->LockDevice(user_)) {
    case policy::EnterpriseInstallAttributes::LOCK_SUCCESS: {
      // Proceed with policy fetch.
      policy::BrowserPolicyConnector* connector =
          g_browser_process->browser_policy_connector();
      connector->FetchCloudPolicy();
      return;
    }
    case policy::EnterpriseInstallAttributes::LOCK_NOT_READY: {
      // InstallAttributes not ready yet, retry later.
      LOG(WARNING) << "Install Attributes not ready yet will retry in "
                   << kLockRetryIntervalMs << "ms.";
      MessageLoop::current()->PostDelayedTask(
          FROM_HERE,
          base::Bind(&EnterpriseEnrollmentScreen::WriteInstallAttributesData,
                     weak_ptr_factory_.GetWeakPtr()),
          base::TimeDelta::FromMilliseconds(kLockRetryIntervalMs));
      return;
    }
    case policy::EnterpriseInstallAttributes::LOCK_BACKEND_ERROR: {
      actor_->ShowFatalEnrollmentError();
      return;
    }
    case policy::EnterpriseInstallAttributes::LOCK_WRONG_USER: {
      LOG(ERROR) << "Enrollment can not proceed because the InstallAttrs "
                 << "has been locked already!";
      actor_->ShowFatalEnrollmentError();
      return;
    }
  }

  NOTREACHED();
}

void EnterpriseEnrollmentScreen::RegisterForDevicePolicy(
    const std::string& token) {
  policy::BrowserPolicyConnector* connector =
      g_browser_process->browser_policy_connector();
  if (!connector->device_cloud_policy_subsystem()) {
    LOG(ERROR) << "Cloud policy subsystem not initialized.";
  } else if (connector->IsEnterpriseManaged()) {
    LOG(ERROR) << "Device is already enterprise managed!";
  } else if (connector->device_cloud_policy_subsystem()->state() ==
      policy::CloudPolicySubsystem::SUCCESS) {
    LOG(ERROR) << "A previous enrollment already succeeded!";
  } else {
    // Make sure the device policy subsystem is in a clean slate.
    connector->ResetDevicePolicy();
    connector->ScheduleServiceInitialization(0);
    registrar_.reset(new policy::CloudPolicySubsystem::ObserverRegistrar(
        connector->device_cloud_policy_subsystem(), this));
    // Push the credentials to the policy infrastructure. It'll start enrollment
    // and notify us of progress through CloudPolicySubsystem::Observer.
    connector->RegisterForDevicePolicy(user_, token, is_auto_enrollment_);
    return;
  }
  NOTREACHED();
  if (is_showing_)
    actor_->ShowFatalEnrollmentError();
}

}  // namespace chromeos
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/base/filter_host.h"
#include "media/filters/null_audio_renderer.h"

namespace media {

// The number of reads to perform during initialization for preroll purposes.
static const size_t kInitialReads = 16;

// The number of buffers we consume before sleeping.  By doing so we can sleep
// for longer, reducing CPU load and avoiding situations where audio samples
// are so short that the OS sleeps our thread for too long.
static const size_t kBuffersPerSleep = 4;

NullAudioRenderer::NullAudioRenderer()
    : decoder_(NULL),
      playback_rate_(0.0f),
      thread_(NULL),
      initialized_(false),
      shutdown_(false) {
}

NullAudioRenderer::~NullAudioRenderer() {
  Stop();
}

// static
bool NullAudioRenderer::IsMediaFormatSupported(
    const MediaFormat* media_format) {
  DCHECK(media_format);
  std::string mime_type;
  return media_format->GetAsString(MediaFormat::kMimeType, &mime_type) &&
      mime_type.compare(mime_type::kUncompressedAudio) == 0;
}

void NullAudioRenderer::Stop() {
  shutdown_ = true;
  if (thread_)
    PlatformThread::Join(thread_);
}

void NullAudioRenderer::SetPlaybackRate(float playback_rate) {
  playback_rate_ = playback_rate;
}

bool NullAudioRenderer::Initialize(AudioDecoder* decoder) {
  DCHECK(decoder);
  decoder_ = decoder;

  // It's safe to start the thread now because it simply sleeps when playback
  // rate is 0.0f.
  if (!PlatformThread::Create(0, this, &thread_))
    return false;

  // Schedule our initial reads.
  for (size_t i = 0; i < kInitialReads; ++i) {
    ScheduleRead();
  }

  // Defer initialization until all scheduled reads have completed.
  return true;
}

void NullAudioRenderer::SetVolume(float volume) {
  // Do nothing.
}

void NullAudioRenderer::OnAssignment(Buffer* buffer_in) {
  bool initialized = false;
  {
    AutoLock auto_lock(input_lock_);
    buffer_in->AddRef();
    input_queue_.push_back(buffer_in);
    DCHECK(input_queue_.size() <= kInitialReads);

    // See if we're finally initialized.
    // TODO(scherkus): handle end of stream.
    initialized = !initialized_ && input_queue_.size() == kInitialReads;
  }

  if (initialized) {
    initialized_ = true;
    host_->InitializationComplete();
  }
}

void NullAudioRenderer::ThreadMain() {
  // Loop until we're signaled to stop.
  while (!shutdown_) {
    base::TimeDelta timestamp;
    base::TimeDelta duration;
    int sleep_ms = 0;
    int released_buffers = 0;

    // Only consume buffers when actually playing.
    if (playback_rate_ > 0.0f) {
      AutoLock auto_lock(input_lock_);
      for (size_t i = 0; i < kBuffersPerSleep && !input_queue_.empty(); ++i) {
        scoped_refptr<Buffer> buffer = input_queue_.front();
        input_queue_.pop_front();
        buffer->Release();
        timestamp = buffer->GetTimestamp();
        duration += buffer->GetDuration();
        ++released_buffers;
      }
      // Apply the playback rate to our sleep duration.
      sleep_ms =
          static_cast<int>(floor(duration.InMillisecondsF() / playback_rate_));
    }

    // Schedule reads for every released buffer to maintain "playback".
    for (int i = 0; i < released_buffers; ++i) {
      ScheduleRead();
    }

    // Sleep and update the clock when we wake up.
    PlatformThread::Sleep(sleep_ms);
    if (timestamp.InMicroseconds() > 0) {
      host_->SetTime(timestamp);
    }
  }
}

void NullAudioRenderer::ScheduleRead() {
  host_->PostTask(NewRunnableMethod(decoder_, &AudioDecoder::Read,
      new AssignableBuffer<NullAudioRenderer, Buffer>(this)));
}

}  // namespace media
<commit_msg>Fixed NullAudioRenderer gcc break due to not including <cmath>.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <cmath>

#include "media/base/filter_host.h"
#include "media/filters/null_audio_renderer.h"

namespace media {

// The number of reads to perform during initialization for preroll purposes.
static const size_t kInitialReads = 16;

// The number of buffers we consume before sleeping.  By doing so we can sleep
// for longer, reducing CPU load and avoiding situations where audio samples
// are so short that the OS sleeps our thread for too long.
static const size_t kBuffersPerSleep = 4;

NullAudioRenderer::NullAudioRenderer()
    : decoder_(NULL),
      playback_rate_(0.0f),
      thread_(NULL),
      initialized_(false),
      shutdown_(false) {
}

NullAudioRenderer::~NullAudioRenderer() {
  Stop();
}

// static
bool NullAudioRenderer::IsMediaFormatSupported(
    const MediaFormat* media_format) {
  DCHECK(media_format);
  std::string mime_type;
  return media_format->GetAsString(MediaFormat::kMimeType, &mime_type) &&
      mime_type.compare(mime_type::kUncompressedAudio) == 0;
}

void NullAudioRenderer::Stop() {
  shutdown_ = true;
  if (thread_)
    PlatformThread::Join(thread_);
}

void NullAudioRenderer::SetPlaybackRate(float playback_rate) {
  playback_rate_ = playback_rate;
}

bool NullAudioRenderer::Initialize(AudioDecoder* decoder) {
  DCHECK(decoder);
  decoder_ = decoder;

  // It's safe to start the thread now because it simply sleeps when playback
  // rate is 0.0f.
  if (!PlatformThread::Create(0, this, &thread_))
    return false;

  // Schedule our initial reads.
  for (size_t i = 0; i < kInitialReads; ++i) {
    ScheduleRead();
  }

  // Defer initialization until all scheduled reads have completed.
  return true;
}

void NullAudioRenderer::SetVolume(float volume) {
  // Do nothing.
}

void NullAudioRenderer::OnAssignment(Buffer* buffer_in) {
  bool initialized = false;
  {
    AutoLock auto_lock(input_lock_);
    buffer_in->AddRef();
    input_queue_.push_back(buffer_in);
    DCHECK(input_queue_.size() <= kInitialReads);

    // See if we're finally initialized.
    // TODO(scherkus): handle end of stream.
    initialized = !initialized_ && input_queue_.size() == kInitialReads;
  }

  if (initialized) {
    initialized_ = true;
    host_->InitializationComplete();
  }
}

void NullAudioRenderer::ThreadMain() {
  // Loop until we're signaled to stop.
  while (!shutdown_) {
    base::TimeDelta timestamp;
    base::TimeDelta duration;
    int sleep_ms = 0;
    int released_buffers = 0;

    // Only consume buffers when actually playing.
    if (playback_rate_ > 0.0f) {
      AutoLock auto_lock(input_lock_);
      for (size_t i = 0; i < kBuffersPerSleep && !input_queue_.empty(); ++i) {
        scoped_refptr<Buffer> buffer = input_queue_.front();
        input_queue_.pop_front();
        buffer->Release();
        timestamp = buffer->GetTimestamp();
        duration += buffer->GetDuration();
        ++released_buffers;
      }
      // Apply the playback rate to our sleep duration.
      sleep_ms =
          static_cast<int>(floor(duration.InMillisecondsF() / playback_rate_));
    }

    // Schedule reads for every released buffer to maintain "playback".
    for (int i = 0; i < released_buffers; ++i) {
      ScheduleRead();
    }

    // Sleep and update the clock when we wake up.
    PlatformThread::Sleep(sleep_ms);
    if (timestamp.InMicroseconds() > 0) {
      host_->SetTime(timestamp);
    }
  }
}

void NullAudioRenderer::ScheduleRead() {
  host_->PostTask(NewRunnableMethod(decoder_, &AudioDecoder::Read,
      new AssignableBuffer<NullAudioRenderer, Buffer>(this)));
}

}  // namespace media
<|endoftext|>