<commit_before>#include "SDBPShardConnection.h"
#include "SDBPClient.h"
#include "Application/Common/ClientResponse.h"
#include "Application/SDBP/SDBPRequestMessage.h"
#include "Application/SDBP/SDBPResponseMessage.h"

#define CONN_BUFSIZE    4096

#define CLIENT_MUTEX_GUARD_DECLARE()    MutexGuard mutexGuard(client->mutex)
#define CLIENT_MUTEX_LOCK()             mutexGuard.Lock()
#define CLIENT_MUTEX_UNLOCK()           mutexGuard.Unlock()

using namespace SDBPClient;

static bool LessThan(uint64_t a, uint64_t b)
{
    return a < b;
}

ShardConnection::ShardConnection(Client* client_, uint64_t nodeID_, Endpoint& endpoint_)
{
    client = client_;
    nodeID = nodeID_;
    endpoint = endpoint_;
    autoFlush = false;
    isBulkSent = false;
    Connect();
}

void ShardConnection::Connect()
{
//    Log_Debug("Connecting to %s", endpoint.ToString());
    MessageConnection::Connect(endpoint);
}

bool ShardConnection::SendRequest(Request* request)
{
    SDBPRequestMessage  msg;

    if (!request->isBulk)
    {
        sentRequests.Append(request);
        request->numTry++;
        request->requestTime = EventLoop::Now();
    }

    msg.request = request;
    Write(msg);

//    if (request->numTry > 1)
//        Log_Debug("Resending, commandID: %U, conn: %s", request->commandID, endpoint.ToString());

    //Log_Debug("Sending conn: %s, writeBuffer = %B", endpoint.ToString(), writeBuffer);

    // buffer is saturated
    if (writeBuffer->GetLength() >= MESSAGING_BUFFER_THRESHOLD)
        return false;

    return true;
}

void ShardConnection::SendSubmit(uint64_t /*quorumID*/)
{
    Flush();
}

void ShardConnection::Flush()
{
    FlushWriteBuffer();
}

uint64_t ShardConnection::GetNodeID()
{
    return nodeID;
}

Endpoint& ShardConnection::GetEndpoint()
{
    return endpoint;
}

bool ShardConnection::IsWritePending()
{
    return tcpwrite.active;
}

void ShardConnection::SetQuorumMembership(uint64_t quorumID)
{
    // SortedList takes care of unique IDs
    quorums.Add(quorumID, true);
}

void ShardConnection::ClearQuorumMembership(uint64_t quorumID)
{
    quorums.Remove(quorumID);
}

void ShardConnection::ClearQuorumMemberships()
{
    quorums.Clear();
}

SortedList<uint64_t>& ShardConnection::GetQuorumList()
{
    return quorums;
}

bool ShardConnection::OnMessage(ReadBuffer& rbuf)
{
    SDBPResponseMessage msg;
    Request*            it;
    uint64_t            quorumID;

    CLIENT_MUTEX_GUARD_DECLARE();

    //Log_Debug("Shard conn: %s, message: %R", endpoint.ToString(), &rbuf);

    response.Init();
    msg.response = &response;
    if (!msg.Read(rbuf))
        return false;

    // find the request in sent requests by commandID
    FOREACH (it, sentRequests)
    {
        if (it->commandID == response.commandID)
        {
            // TODO: what to do when the first in the queue returns NOSERVICE
            // but the others return OK ?!?

            // invalidate quorum state on NOSERVICE response
            if (response.type == CLIENTRESPONSE_NOSERVICE)
            {
                quorumID = it->quorumID;
                InvalidateQuorum(quorumID);
                return false;
            }

            sentRequests.Remove(it);
            break;
        }
    }

    client->result->AppendRequestResponse(&response);
    response.Init();

    return false;
}

void ShardConnection::OnWrite()
{
    CLIENT_MUTEX_GUARD_DECLARE();

    MessageConnection::OnWrite();
    if (client->IsBulkLoading() && !isBulkSent)
        isBulkSent = true;

    SendQuorumRequests();
}

void ShardConnection::OnConnect()
{
    Log_Trace();
    //Log_Debug("Shard connection connected, endpoint: %s", endpoint.ToString());

    CLIENT_MUTEX_GUARD_DECLARE();

    MessageConnection::OnConnect();
    if (client->IsBulkLoading() && !isBulkSent)
    {
        SendBulkLoadingRequest();
        return;
    }

    SendQuorumRequests();
}

void ShardConnection::OnClose()
{
//    Log_Debug("Shard connection closing: %s", endpoint.ToString());

    Request*    it;
    Request*    prev;
    uint64_t*   itQuorum;
    uint64_t*   itNext;

    CLIENT_MUTEX_GUARD_DECLARE();

    isBulkSent = false;

    // close the socket and try reconnecting
    MessageConnection::OnClose();

    // restart reconnection with timeout
    EventLoop::Reset(&connectTimeout);

    // invalidate quorums
    for (itQuorum = quorums.First(); itQuorum != NULL; itQuorum = itNext)
    {
        itNext = quorums.Next(itQuorum);
        InvalidateQuorum(*itQuorum);
    }

    // put back requests that have no response to the client's quorum queue
    for (it = sentRequests.Last(); it != NULL; it = prev)
    {
        prev = sentRequests.Prev(it);
        sentRequests.Remove(it);
        client->AddRequestToQuorum(it, false);
    }
}

void ShardConnection::InvalidateQuorum(uint64_t quorumID)
{
    Request*    it;
    Request*    prev;

    for (it = sentRequests.Last(); it != NULL; it = prev)
    {
        prev = sentRequests.Prev(it);
        if (it->quorumID == quorumID)
        {
            sentRequests.Remove(it);
            client->AddRequestToQuorum(it, false);
        }
    }

    client->InvalidateQuorum(quorumID, nodeID);
}

void ShardConnection::SendQuorumRequests()
{
    uint64_t*   qit;

    // notify the client so that it can assign the requests to the connection
    FOREACH (qit, quorums)
        client->SendQuorumRequest(this, *qit);
}

void ShardConnection::SendBulkLoadingRequest()
{
    Request req;

    req.BulkLoading(0);
    req.isBulk = true;

    SendRequest(&req);
    Flush();
}
<commit_msg>Fixed NOSERVICE handling in client.<commit_after>#include "SDBPShardConnection.h"
#include "SDBPClient.h"
#include "Application/Common/ClientResponse.h"
#include "Application/SDBP/SDBPRequestMessage.h"
#include "Application/SDBP/SDBPResponseMessage.h"

#define CONN_BUFSIZE    4096

#define CLIENT_MUTEX_GUARD_DECLARE()    MutexGuard mutexGuard(client->mutex)
#define CLIENT_MUTEX_LOCK()             mutexGuard.Lock()
#define CLIENT_MUTEX_UNLOCK()           mutexGuard.Unlock()

using namespace SDBPClient;

static bool LessThan(uint64_t a, uint64_t b)
{
    return a < b;
}

ShardConnection::ShardConnection(Client* client_, uint64_t nodeID_, Endpoint& endpoint_)
{
    client = client_;
    nodeID = nodeID_;
    endpoint = endpoint_;
    autoFlush = false;
    isBulkSent = false;
    Connect();
}

void ShardConnection::Connect()
{
//    Log_Debug("Connecting to %s", endpoint.ToString());
    MessageConnection::Connect(endpoint);
}

bool ShardConnection::SendRequest(Request* request)
{
    SDBPRequestMessage  msg;

    if (!request->isBulk)
    {
        sentRequests.Append(request);
        request->numTry++;
        request->requestTime = EventLoop::Now();
    }

    msg.request = request;
    Write(msg);

//    if (request->numTry > 1)
//        Log_Debug("Resending, commandID: %U, conn: %s", request->commandID, endpoint.ToString());

    //Log_Debug("Sending conn: %s, writeBuffer = %B", endpoint.ToString(), writeBuffer);

    // buffer is saturated
    if (writeBuffer->GetLength() >= MESSAGING_BUFFER_THRESHOLD)
        return false;

    return true;
}

void ShardConnection::SendSubmit(uint64_t /*quorumID*/)
{
    Flush();
}

void ShardConnection::Flush()
{
    FlushWriteBuffer();
}

uint64_t ShardConnection::GetNodeID()
{
    return nodeID;
}

Endpoint& ShardConnection::GetEndpoint()
{
    return endpoint;
}

bool ShardConnection::IsWritePending()
{
    return tcpwrite.active;
}

void ShardConnection::SetQuorumMembership(uint64_t quorumID)
{
    // SortedList takes care of unique IDs
    quorums.Add(quorumID, true);
}

void ShardConnection::ClearQuorumMembership(uint64_t quorumID)
{
    quorums.Remove(quorumID);
}

void ShardConnection::ClearQuorumMemberships()
{
    quorums.Clear();
}

SortedList<uint64_t>& ShardConnection::GetQuorumList()
{
    return quorums;
}

bool ShardConnection::OnMessage(ReadBuffer& rbuf)
{
    SDBPResponseMessage msg;
    Request*            request;

    CLIENT_MUTEX_GUARD_DECLARE();

    //Log_Debug("Shard conn: %s, message: %R", endpoint.ToString(), &rbuf);

    response.Init();
    msg.response = &response;
    if (!msg.Read(rbuf))
        return false;

    // find the request in sent requests by commandID
    FOREACH (request, sentRequests)
    {
        if (request->commandID == response.commandID)
        {
            // put back the request to the quorum queue and
            // invalidate quorum state on NOSERVICE response
            if (response.type == CLIENTRESPONSE_NOSERVICE)
            {
                sentRequests.Remove(request);
                client->AddRequestToQuorum(request, false);
                client->InvalidateQuorum(request->quorumID, nodeID);
                return false;
            }

            sentRequests.Remove(request);
            break;
        }
    }

    client->result->AppendRequestResponse(&response);
    response.Init();

    return false;
}

void ShardConnection::OnWrite()
{
    CLIENT_MUTEX_GUARD_DECLARE();

    MessageConnection::OnWrite();
    if (client->IsBulkLoading() && !isBulkSent)
        isBulkSent = true;

    SendQuorumRequests();
}

void ShardConnection::OnConnect()
{
    Log_Trace();
    //Log_Debug("Shard connection connected, endpoint: %s", endpoint.ToString());

    CLIENT_MUTEX_GUARD_DECLARE();

    MessageConnection::OnConnect();
    if (client->IsBulkLoading() && !isBulkSent)
    {
        SendBulkLoadingRequest();
        return;
    }

    SendQuorumRequests();
}

void ShardConnection::OnClose()
{
//    Log_Debug("Shard connection closing: %s", endpoint.ToString());

    Request*    it;
    Request*    prev;
    uint64_t*   itQuorum;
    uint64_t*   itNext;

    CLIENT_MUTEX_GUARD_DECLARE();

    isBulkSent = false;

    // close the socket and try reconnecting
    MessageConnection::OnClose();

    // restart reconnection with timeout
    EventLoop::Reset(&connectTimeout);

    // invalidate quorums
    for (itQuorum = quorums.First(); itQuorum != NULL; itQuorum = itNext)
    {
        itNext = quorums.Next(itQuorum);
        InvalidateQuorum(*itQuorum);
    }

    // put back requests that have no response to the client's quorum queue
    for (it = sentRequests.Last(); it != NULL; it = prev)
    {
        prev = sentRequests.Prev(it);
        sentRequests.Remove(it);
        client->AddRequestToQuorum(it, false);
    }
}

void ShardConnection::InvalidateQuorum(uint64_t quorumID)
{
    Request*    it;
    Request*    prev;

    for (it = sentRequests.Last(); it != NULL; it = prev)
    {
        prev = sentRequests.Prev(it);
        if (it->quorumID == quorumID)
        {
            sentRequests.Remove(it);
            client->AddRequestToQuorum(it, false);
        }
    }

    client->InvalidateQuorum(quorumID, nodeID);
}

void ShardConnection::SendQuorumRequests()
{
    uint64_t*   qit;

    // notify the client so that it can assign the requests to the connection
    FOREACH (qit, quorums)
        client->SendQuorumRequest(this, *qit);
}

void ShardConnection::SendBulkLoadingRequest()
{
    Request req;

    req.BulkLoading(0);
    req.isBulk = true;

    SendRequest(&req);
    Flush();
}
<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow 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 <iostream>
#include <vector>

#include "tensorflow/contrib/tensorboard/db/schema.h"
#include "tensorflow/contrib/tensorboard/db/summary_db_writer.h"
#include "tensorflow/core/lib/db/sqlite.h"
#include "tensorflow/core/lib/io/record_reader.h"
#include "tensorflow/core/platform/init_main.h"
#include "tensorflow/core/util/command_line_flags.h"
#include "tensorflow/core/util/event.pb.h"

namespace tensorflow {
namespace {

template <typename T>
string AddCommas(T n) {
  static_assert(std::is_integral<T>::value, "is_integral");
  string s = strings::StrCat(n);
  if (s.size() > 3) {
    int extra = s.size() / 3 - (s.size() % 3 == 0 ? 1 : 0);
    s.append(extra, 'X');
    int c = 0;
    for (int i = s.size() - 1; i > 0; --i) {
      s[i] = s[i - extra];
      if (++c % 3 == 0) {
        s[--i] = ',';
        --extra;
      }
    }
  }
  return s;
}

int main(int argc, char* argv[]) {
  string path;
  string events;
  string experiment_name;
  string run_name;
  string user_name;
  std::vector<Flag> flag_list = {
      Flag("db", &path, "Path of SQLite DB file"),
      Flag("events", &events, "TensorFlow record proto event log file"),
      Flag("experiment_name", &experiment_name, "The DB experiment_name value"),
      Flag("run_name", &run_name, "The DB run_name value"),
      Flag("user_name", &user_name, "The DB user_name value"),
  };
  string usage = Flags::Usage(argv[0], flag_list);
  bool parse_result = Flags::Parse(&argc, argv, flag_list);
  if (!parse_result || path.empty()) {
    std::cerr << "The loader tool imports tf.Event record files, created by\n"
              << "SummaryFileWriter, into the sorts of SQLite database files\n"
              << "created by SummaryDbWriter.\n\n"
              << "In addition to the flags below, the environment variables\n"
              << "defined by core/lib/db/sqlite.cc can also be set.\n\n"
              << usage;
    return -1;
  }
  port::InitMain(argv[0], &argc, &argv);
  Env* env = Env::Default();

  LOG(INFO) << "Opening SQLite file: " << path;
  Sqlite* db;
  TF_CHECK_OK(Sqlite::Open(
      path, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX,
      &db));
  core::ScopedUnref unref_db(db);

  LOG(INFO) << "Initializing TensorBoard schema";
  TF_CHECK_OK(SetupTensorboardSqliteDb(db));

  LOG(INFO) << "Creating SummaryDbWriter";
  SummaryWriterInterface* db_writer;
  TF_CHECK_OK(CreateSummaryDbWriter(db, experiment_name, run_name, user_name,
                                    env, &db_writer));
  core::ScopedUnref unref(db_writer);

  LOG(INFO) << "Loading TF event log: " << events;
  std::unique_ptr<RandomAccessFile> file;
  TF_CHECK_OK(env->NewRandomAccessFile(events, &file));
  io::RecordReader reader(file.get());

  uint64 start = env->NowMicros();
  uint64 records = 0;
  uint64 offset = 0;
  string record;
  while (true) {
    std::unique_ptr<Event> event = std::unique_ptr<Event>(new Event);
    Status s = reader.ReadRecord(&offset, &record);
    if (s.code() == error::OUT_OF_RANGE) break;
    TF_CHECK_OK(s);
    if (!ParseProtoUnlimited(event.get(), record)) {
      LOG(FATAL) << "Corrupt tf.Event record"
                 << " offset=" << (offset - record.size())
                 << " size=" << static_cast<int>(record.size());
    }
    TF_CHECK_OK(db_writer->WriteEvent(std::move(event)));
    ++records;
  }
  uint64 elapsed = env->NowMicros() - start;
  LOG(INFO) << "Loaded " << AddCommas(offset) << " bytes with "
            << AddCommas(records) << " records at "
            << AddCommas(offset / (elapsed / 1000000)) << " bps";

  return 0;
}

}  // namespace
}  // namespace tensorflow

int main(int argc, char* argv[]) { return tensorflow::main(argc, argv); }
<commit_msg>Fix floating point exception with bps calculation 	modified:   tensorflow/contrib/tensorboard/db/loader.cc<commit_after>/* Copyright 2017 The TensorFlow 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 <iostream>
#include <vector>

#include "tensorflow/contrib/tensorboard/db/schema.h"
#include "tensorflow/contrib/tensorboard/db/summary_db_writer.h"
#include "tensorflow/core/lib/db/sqlite.h"
#include "tensorflow/core/lib/io/record_reader.h"
#include "tensorflow/core/platform/init_main.h"
#include "tensorflow/core/util/command_line_flags.h"
#include "tensorflow/core/util/event.pb.h"

namespace tensorflow {
namespace {

template <typename T>
string AddCommas(T n) {
  static_assert(std::is_integral<T>::value, "is_integral");
  string s = strings::StrCat(n);
  if (s.size() > 3) {
    int extra = s.size() / 3 - (s.size() % 3 == 0 ? 1 : 0);
    s.append(extra, 'X');
    int c = 0;
    for (int i = s.size() - 1; i > 0; --i) {
      s[i] = s[i - extra];
      if (++c % 3 == 0) {
        s[--i] = ',';
        --extra;
      }
    }
  }
  return s;
}

int main(int argc, char* argv[]) {
  string path;
  string events;
  string experiment_name;
  string run_name;
  string user_name;
  std::vector<Flag> flag_list = {
      Flag("db", &path, "Path of SQLite DB file"),
      Flag("events", &events, "TensorFlow record proto event log file"),
      Flag("experiment_name", &experiment_name, "The DB experiment_name value"),
      Flag("run_name", &run_name, "The DB run_name value"),
      Flag("user_name", &user_name, "The DB user_name value"),
  };
  string usage = Flags::Usage(argv[0], flag_list);
  bool parse_result = Flags::Parse(&argc, argv, flag_list);
  if (!parse_result || path.empty()) {
    std::cerr << "The loader tool imports tf.Event record files, created by\n"
              << "SummaryFileWriter, into the sorts of SQLite database files\n"
              << "created by SummaryDbWriter.\n\n"
              << "In addition to the flags below, the environment variables\n"
              << "defined by core/lib/db/sqlite.cc can also be set.\n\n"
              << usage;
    return -1;
  }
  port::InitMain(argv[0], &argc, &argv);
  Env* env = Env::Default();

  LOG(INFO) << "Opening SQLite file: " << path;
  Sqlite* db;
  TF_CHECK_OK(Sqlite::Open(
      path, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX,
      &db));
  core::ScopedUnref unref_db(db);

  LOG(INFO) << "Initializing TensorBoard schema";
  TF_CHECK_OK(SetupTensorboardSqliteDb(db));

  LOG(INFO) << "Creating SummaryDbWriter";
  SummaryWriterInterface* db_writer;
  TF_CHECK_OK(CreateSummaryDbWriter(db, experiment_name, run_name, user_name,
                                    env, &db_writer));
  core::ScopedUnref unref(db_writer);

  LOG(INFO) << "Loading TF event log: " << events;
  std::unique_ptr<RandomAccessFile> file;
  TF_CHECK_OK(env->NewRandomAccessFile(events, &file));
  io::RecordReader reader(file.get());

  uint64 start = env->NowMicros();
  uint64 records = 0;
  uint64 offset = 0;
  string record;
  while (true) {
    std::unique_ptr<Event> event = std::unique_ptr<Event>(new Event);
    Status s = reader.ReadRecord(&offset, &record);
    if (s.code() == error::OUT_OF_RANGE) break;
    TF_CHECK_OK(s);
    if (!ParseProtoUnlimited(event.get(), record)) {
      LOG(FATAL) << "Corrupt tf.Event record"
                 << " offset=" << (offset - record.size())
                 << " size=" << static_cast<int>(record.size());
    }
    TF_CHECK_OK(db_writer->WriteEvent(std::move(event)));
    ++records;
  }
  uint64 elapsed = env->NowMicros() - start;
  LOG(INFO) << "Loaded " << AddCommas(offset) << " bytes with "
            << AddCommas(records) << " records";
  if (elapsed > 0) {
    LOG(INFO) << "bps=" << (uint64)(offset / (elapsed / 1000000.0));
  }

  return 0;
}

}  // namespace
}  // namespace tensorflow

int main(int argc, char* argv[]) { return tensorflow::main(argc, argv); }
<|endoftext|>


<commit_before>#include "catch.hpp"

#include <initializer_list>

#include "cxxopts.hpp"

class Argv {
  public:

  Argv(std::initializer_list<const char*> args)
  : m_argv(new char*[args.size()])
  , m_argc(args.size())
  {
    int i = 0;
    auto iter = args.begin();
    while (iter != args.end()) {
      auto len = strlen(*iter) + 1;
      auto ptr = std::unique_ptr<char[]>(new char[len]);

      strcpy(ptr.get(), *iter);
      m_args.push_back(std::move(ptr));
      m_argv.get()[i] = m_args.back().get();

      ++iter;
      ++i;
    }
  }

  char** argv() const {
    return m_argv.get();
  }

  int argc() const {
    return m_argc;
  }

  private:

  std::vector<std::unique_ptr<char[]>> m_args;
  std::unique_ptr<char*[]> m_argv;
  int m_argc;
};

TEST_CASE("Basic options", "[options]")
{

  cxxopts::Options options("tester", " - test basic options");

  options.add_options()
    ("long", "a long option")
    ("s,short", "a short option")
    ("value", "an option with a value", cxxopts::value<std::string>())
    ("a,av", "a short option with a value", cxxopts::value<std::string>())
    ("6,six", "a short number option")
    ("p, space", "an option with space between short and long")
    ;

  Argv argv({
    "tester",
    "--long",
    "-s",
    "--value",
    "value",
    "-a",
    "b",
    "-6",
    "-p",
    "--space",
  });

  char** actual_argv = argv.argv();
  auto argc = argv.argc();

  auto result = options.parse(argc, actual_argv);

  CHECK(result.count("long") == 1);
  CHECK(result.count("s") == 1);
  CHECK(result.count("value") == 1);
  CHECK(result.count("a") == 1);
  CHECK(result["value"].as<std::string>() == "value");
  CHECK(result["a"].as<std::string>() == "b");
  CHECK(result.count("6") == 1);
  CHECK(result.count("p") == 2);
  CHECK(result.count("space") == 2);
}

TEST_CASE("Short options", "[options]")
{
  cxxopts::Options options("test_short", " - test short options");

  options.add_options()
    ("a", "a short option", cxxopts::value<std::string>());

  Argv argv({"test_short", "-a", "value"});

  auto actual_argv = argv.argv();
  auto argc = argv.argc();

  auto result = options.parse(argc, actual_argv);

  CHECK(result.count("a") == 1);
  CHECK(result["a"].as<std::string>() == "value");

  REQUIRE_THROWS_AS(options.add_options()("", "nothing option"),
    cxxopts::invalid_option_format_error);
}

TEST_CASE("No positional", "[positional]")
{
  cxxopts::Options options("test_no_positional",
    " - test no positional options");

  Argv av({"tester", "a", "b", "def"});

  char** argv = av.argv();
  auto argc = av.argc();
  auto result = options.parse(argc, argv);

  REQUIRE(argc == 4);
  CHECK(strcmp(argv[1], "a") == 0);
}

TEST_CASE("All positional", "[positional]")
{
  std::vector<std::string> positional;

  cxxopts::Options options("test_all_positional", " - test all positional");
  options.add_options()
    ("positional", "Positional parameters",
      cxxopts::value<std::vector<std::string>>(positional))
  ;

  Argv av({"tester", "a", "b", "c"});

  auto argc = av.argc();
  auto argv = av.argv();

  options.parse_positional("positional");

  auto result = options.parse(argc, argv);

  REQUIRE(argc == 1);
  REQUIRE(positional.size() == 3);

  CHECK(positional[0] == "a");
  CHECK(positional[1] == "b");
  CHECK(positional[2] == "c");
}

TEST_CASE("Some positional explicit", "[positional]")
{
  cxxopts::Options options("positional_explicit", " - test positional");

  options.add_options()
    ("input", "Input file", cxxopts::value<std::string>())
    ("output", "Output file", cxxopts::value<std::string>())
    ("positional", "Positional parameters",
      cxxopts::value<std::vector<std::string>>())
  ;

  options.parse_positional({"input", "output", "positional"});

  Argv av({"tester", "--output", "a", "b", "c", "d"});

  char** argv = av.argv();
  auto argc = av.argc();

  auto result = options.parse(argc, argv);

  CHECK(argc == 1);
  CHECK(result.count("output"));
  CHECK(result["input"].as<std::string>() == "b");
  CHECK(result["output"].as<std::string>() == "a");

  auto& positional = result["positional"].as<std::vector<std::string>>();

  REQUIRE(positional.size() == 2);
  CHECK(positional[0] == "c");
  CHECK(positional[1] == "d");
}

TEST_CASE("No positional with extras", "[positional]")
{
  cxxopts::Options options("posargmaster", "shows incorrect handling");
  options.add_options()
      ("dummy", "oh no", cxxopts::value<std::string>())
      ;

  Argv av({"extras", "--", "a", "b", "c", "d"});

  char** argv = av.argv();
  auto argc = av.argc();

  auto old_argv = argv;
  auto old_argc = argc;

  options.parse(argc, argv);

  REQUIRE(argc == old_argc - 1);
  CHECK(argv[0] == std::string("extras"));
  CHECK(argv[1] == std::string("a"));
}

TEST_CASE("Empty with implicit value", "[implicit]")
{
  cxxopts::Options options("empty_implicit", "doesn't handle empty");
  options.add_options()
    ("implicit", "Has implicit", cxxopts::value<std::string>()
      ->implicit_value("foo"));

  Argv av({"implicit", "--implicit", ""});

  char** argv = av.argv();
  auto argc = av.argc();

  auto result = options.parse(argc, argv);

  REQUIRE(result.count("implicit") == 1);
  REQUIRE(result["implicit"].as<std::string>() == "");
}

TEST_CASE("Parse into a reference", "[reference]")
{
  int value = 0;

  cxxopts::Options options("into_reference", "parses into a reference");
  options.add_options()
    ("ref", "A reference", cxxopts::value(value));

  Argv av({"into_reference", "--ref", "42"});

  auto argv = av.argv();
  auto argc = av.argc();

  auto result = options.parse(argc, argv);
  CHECK(result.count("ref") == 1);
  CHECK(value == 42);
}

TEST_CASE("Integers", "[options]")
{
  cxxopts::Options options("parses_integers", "parses integers correctly");
  options.add_options()
    ("positional", "Integers", cxxopts::value<std::vector<int>>());

  Argv av({"ints", "--", "5", "6", "-6", "0", "0xab", "0xAf"});

  char** argv = av.argv();
  auto argc = av.argc();

  options.parse_positional("positional");
  auto result = options.parse(argc, argv);

  REQUIRE(result.count("positional") == 6);

  auto& positional = result["positional"].as<std::vector<int>>();
  REQUIRE(positional.size() == 6);
  CHECK(positional[0] == 5);
  CHECK(positional[1] == 6);
  CHECK(positional[2] == -6);
  CHECK(positional[3] == 0);
  CHECK(positional[4] == 0xab);
  CHECK(positional[5] == 0xaf);
}

TEST_CASE("Unsigned integers", "[options]")
{
  cxxopts::Options options("parses_unsigned", "detects unsigned errors");
  options.add_options()
    ("positional", "Integers", cxxopts::value<std::vector<unsigned int>>());

  Argv av({"ints", "--", "-2"});

  char** argv = av.argv();
  auto argc = av.argc();

  options.parse_positional("positional");
  CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type);
}

TEST_CASE("Integer bounds", "[integer]")
{
  cxxopts::Options options("integer_boundaries", "check min/max integer");
  options.add_options()
    ("positional", "Integers", cxxopts::value<std::vector<int8_t>>());

  SECTION("No overflow")
  {
    Argv av({"ints", "--", "127", "-128", "0x7f", "-0x80", "0x7e"});

    auto argv = av.argv();
    auto argc = av.argc();

    options.parse_positional("positional");
    auto result = options.parse(argc, argv);

    REQUIRE(result.count("positional") == 5);

    auto& positional = result["positional"].as<std::vector<int8_t>>();
    CHECK(positional[0] == 127);
    CHECK(positional[1] == -128);
    CHECK(positional[2] == 0x7f);
    CHECK(positional[3] == -0x80);
    CHECK(positional[4] == 0x7e);
  }
}

TEST_CASE("Overflow on boundary", "[integer]")
{
  using namespace cxxopts::values;

  int8_t si;
  uint8_t ui;

  CHECK_THROWS_AS((integer_parser("128", si)), cxxopts::argument_incorrect_type);
  CHECK_THROWS_AS((integer_parser("-129", si)), cxxopts::argument_incorrect_type);
  CHECK_THROWS_AS((integer_parser("256", ui)), cxxopts::argument_incorrect_type);
  CHECK_THROWS_AS((integer_parser("-0x81", si)), cxxopts::argument_incorrect_type);
  CHECK_THROWS_AS((integer_parser("0x80", si)), cxxopts::argument_incorrect_type);
  CHECK_THROWS_AS((integer_parser("0x100", ui)), cxxopts::argument_incorrect_type);
}

TEST_CASE("Integer overflow", "[options]")
{
  cxxopts::Options options("reject_overflow", "rejects overflowing integers");
  options.add_options()
    ("positional", "Integers", cxxopts::value<std::vector<int8_t>>());

  Argv av({"ints", "--", "128"});

  auto argv = av.argv();
  auto argc = av.argc();

  options.parse_positional("positional");
  CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type);
}

TEST_CASE("Floats", "[options]")
{
  cxxopts::Options options("parses_floats", "parses floats correctly");
  options.add_options()
    ("double", "Double precision", cxxopts::value<double>())
    ("positional", "Floats", cxxopts::value<std::vector<float>>());

  Argv av({"floats", "--double", "0.5", "--", "4", "-4", "1.5e6", "-1.5e6"});

  char** argv = av.argv();
  auto argc = av.argc();

  options.parse_positional("positional");
  auto result = options.parse(argc, argv);

  REQUIRE(result.count("double") == 1);
  REQUIRE(result.count("positional") == 4);

  CHECK(result["double"].as<double>() == 0.5);

  auto& positional = result["positional"].as<std::vector<float>>();
  CHECK(positional[0] == 4);
  CHECK(positional[1] == -4);
  CHECK(positional[2] == 1.5e6);
  CHECK(positional[3] == -1.5e6);
}

<commit_msg>test that fails<commit_after>#include "catch.hpp"

#include <initializer_list>

#include "cxxopts.hpp"

class Argv {
  public:

  Argv(std::initializer_list<const char*> args)
  : m_argv(new char*[args.size()])
  , m_argc(args.size())
  {
    int i = 0;
    auto iter = args.begin();
    while (iter != args.end()) {
      auto len = strlen(*iter) + 1;
      auto ptr = std::unique_ptr<char[]>(new char[len]);

      strcpy(ptr.get(), *iter);
      m_args.push_back(std::move(ptr));
      m_argv.get()[i] = m_args.back().get();

      ++iter;
      ++i;
    }
  }

  char** argv() const {
    return m_argv.get();
  }

  int argc() const {
    return m_argc;
  }

  private:

  std::vector<std::unique_ptr<char[]>> m_args;
  std::unique_ptr<char*[]> m_argv;
  int m_argc;
};

TEST_CASE("Basic options", "[options]")
{

  cxxopts::Options options("tester", " - test basic options");

  options.add_options()
    ("long", "a long option")
    ("s,short", "a short option")
    ("value", "an option with a value", cxxopts::value<std::string>())
    ("a,av", "a short option with a value", cxxopts::value<std::string>())
    ("6,six", "a short number option")
    ("p, space", "an option with space between short and long")
    ;

  Argv argv({
    "tester",
    "--long",
    "-s",
    "--value",
    "value",
    "-a",
    "b",
    "-6",
    "-p",
    "--space",
  });

  char** actual_argv = argv.argv();
  auto argc = argv.argc();

  auto result = options.parse(argc, actual_argv);

  CHECK(result.count("long") == 1);
  CHECK(result.count("s") == 1);
  CHECK(result.count("value") == 1);
  CHECK(result.count("a") == 1);
  CHECK(result["value"].as<std::string>() == "value");
  CHECK(result["a"].as<std::string>() == "b");
  CHECK(result.count("6") == 1);
  CHECK(result.count("p") == 2);
  CHECK(result.count("space") == 2);
}

TEST_CASE("Short options", "[options]")
{
  cxxopts::Options options("test_short", " - test short options");

  options.add_options()
    ("a", "a short option", cxxopts::value<std::string>());

  Argv argv({"test_short", "-a", "value"});

  auto actual_argv = argv.argv();
  auto argc = argv.argc();

  auto result = options.parse(argc, actual_argv);

  CHECK(result.count("a") == 1);
  CHECK(result["a"].as<std::string>() == "value");

  REQUIRE_THROWS_AS(options.add_options()("", "nothing option"),
    cxxopts::invalid_option_format_error);
}

TEST_CASE("No positional", "[positional]")
{
  cxxopts::Options options("test_no_positional",
    " - test no positional options");

  Argv av({"tester", "a", "b", "def"});

  char** argv = av.argv();
  auto argc = av.argc();
  auto result = options.parse(argc, argv);

  REQUIRE(argc == 4);
  CHECK(strcmp(argv[1], "a") == 0);
}

TEST_CASE("All positional", "[positional]")
{
  std::vector<std::string> positional;

  cxxopts::Options options("test_all_positional", " - test all positional");
  options.add_options()
    ("positional", "Positional parameters",
      cxxopts::value<std::vector<std::string>>(positional))
  ;

  Argv av({"tester", "a", "b", "c"});

  auto argc = av.argc();
  auto argv = av.argv();

  options.parse_positional("positional");

  auto result = options.parse(argc, argv);

  REQUIRE(argc == 1);
  REQUIRE(positional.size() == 3);

  CHECK(positional[0] == "a");
  CHECK(positional[1] == "b");
  CHECK(positional[2] == "c");
}

TEST_CASE("Some positional explicit", "[positional]")
{
  cxxopts::Options options("positional_explicit", " - test positional");

  options.add_options()
    ("input", "Input file", cxxopts::value<std::string>())
    ("output", "Output file", cxxopts::value<std::string>())
    ("positional", "Positional parameters",
      cxxopts::value<std::vector<std::string>>())
  ;

  options.parse_positional({"input", "output", "positional"});

  Argv av({"tester", "--output", "a", "b", "c", "d"});

  char** argv = av.argv();
  auto argc = av.argc();

  auto result = options.parse(argc, argv);

  CHECK(argc == 1);
  CHECK(result.count("output"));
  CHECK(result["input"].as<std::string>() == "b");
  CHECK(result["output"].as<std::string>() == "a");

  auto& positional = result["positional"].as<std::vector<std::string>>();

  REQUIRE(positional.size() == 2);
  CHECK(positional[0] == "c");
  CHECK(positional[1] == "d");
}

TEST_CASE("No positional with extras", "[positional]")
{
  cxxopts::Options options("posargmaster", "shows incorrect handling");
  options.add_options()
      ("dummy", "oh no", cxxopts::value<std::string>())
      ;

  Argv av({"extras", "--", "a", "b", "c", "d"});

  char** argv = av.argv();
  auto argc = av.argc();

  auto old_argv = argv;
  auto old_argc = argc;

  options.parse(argc, argv);

  REQUIRE(argc == old_argc - 1);
  CHECK(argv[0] == std::string("extras"));
  CHECK(argv[1] == std::string("a"));
}

TEST_CASE("Empty with implicit value", "[implicit]")
{
  cxxopts::Options options("empty_implicit", "doesn't handle empty");
  options.add_options()
    ("implicit", "Has implicit", cxxopts::value<std::string>()
      ->implicit_value("foo"));

  Argv av({"implicit", "--implicit", ""});

  char** argv = av.argv();
  auto argc = av.argc();

  auto result = options.parse(argc, argv);

  REQUIRE(result.count("implicit") == 1);
  REQUIRE(result["implicit"].as<std::string>() == "");
}

TEST_CASE("Default values", "[default]")
{
  cxxopts::Options options("defaults", "has defaults");
  options.add_options()
    ("default", "Has implicit", cxxopts::value<int>()
      ->default_value("42"));

  SECTION("Sets defaults") {
    Argv av({"implicit"});

    char** argv = av.argv();
    auto argc = av.argc();

    auto result = options.parse(argc, argv);
    CHECK(result.count("default") == 1);
    CHECK(result["default"].as<int>() == 42);
  }

  SECTION("When values provided") {
    Argv av({"implicit", "default", "5"});

    char** argv = av.argv();
    auto argc = av.argc();

    auto result = options.parse(argc, argv);
    CHECK(result.count("default") == 1);
    CHECK(result["default"].as<int>() == 5);
  }
}

TEST_CASE("Parse into a reference", "[reference]")
{
  int value = 0;

  cxxopts::Options options("into_reference", "parses into a reference");
  options.add_options()
    ("ref", "A reference", cxxopts::value(value));

  Argv av({"into_reference", "--ref", "42"});

  auto argv = av.argv();
  auto argc = av.argc();

  auto result = options.parse(argc, argv);
  CHECK(result.count("ref") == 1);
  CHECK(value == 42);
}

TEST_CASE("Integers", "[options]")
{
  cxxopts::Options options("parses_integers", "parses integers correctly");
  options.add_options()
    ("positional", "Integers", cxxopts::value<std::vector<int>>());

  Argv av({"ints", "--", "5", "6", "-6", "0", "0xab", "0xAf"});

  char** argv = av.argv();
  auto argc = av.argc();

  options.parse_positional("positional");
  auto result = options.parse(argc, argv);

  REQUIRE(result.count("positional") == 6);

  auto& positional = result["positional"].as<std::vector<int>>();
  REQUIRE(positional.size() == 6);
  CHECK(positional[0] == 5);
  CHECK(positional[1] == 6);
  CHECK(positional[2] == -6);
  CHECK(positional[3] == 0);
  CHECK(positional[4] == 0xab);
  CHECK(positional[5] == 0xaf);
}

TEST_CASE("Unsigned integers", "[options]")
{
  cxxopts::Options options("parses_unsigned", "detects unsigned errors");
  options.add_options()
    ("positional", "Integers", cxxopts::value<std::vector<unsigned int>>());

  Argv av({"ints", "--", "-2"});

  char** argv = av.argv();
  auto argc = av.argc();

  options.parse_positional("positional");
  CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type);
}

TEST_CASE("Integer bounds", "[integer]")
{
  cxxopts::Options options("integer_boundaries", "check min/max integer");
  options.add_options()
    ("positional", "Integers", cxxopts::value<std::vector<int8_t>>());

  SECTION("No overflow")
  {
    Argv av({"ints", "--", "127", "-128", "0x7f", "-0x80", "0x7e"});

    auto argv = av.argv();
    auto argc = av.argc();

    options.parse_positional("positional");
    auto result = options.parse(argc, argv);

    REQUIRE(result.count("positional") == 5);

    auto& positional = result["positional"].as<std::vector<int8_t>>();
    CHECK(positional[0] == 127);
    CHECK(positional[1] == -128);
    CHECK(positional[2] == 0x7f);
    CHECK(positional[3] == -0x80);
    CHECK(positional[4] == 0x7e);
  }
}

TEST_CASE("Overflow on boundary", "[integer]")
{
  using namespace cxxopts::values;

  int8_t si;
  uint8_t ui;

  CHECK_THROWS_AS((integer_parser("128", si)), cxxopts::argument_incorrect_type);
  CHECK_THROWS_AS((integer_parser("-129", si)), cxxopts::argument_incorrect_type);
  CHECK_THROWS_AS((integer_parser("256", ui)), cxxopts::argument_incorrect_type);
  CHECK_THROWS_AS((integer_parser("-0x81", si)), cxxopts::argument_incorrect_type);
  CHECK_THROWS_AS((integer_parser("0x80", si)), cxxopts::argument_incorrect_type);
  CHECK_THROWS_AS((integer_parser("0x100", ui)), cxxopts::argument_incorrect_type);
}

TEST_CASE("Integer overflow", "[options]")
{
  cxxopts::Options options("reject_overflow", "rejects overflowing integers");
  options.add_options()
    ("positional", "Integers", cxxopts::value<std::vector<int8_t>>());

  Argv av({"ints", "--", "128"});

  auto argv = av.argv();
  auto argc = av.argc();

  options.parse_positional("positional");
  CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type);
}

TEST_CASE("Floats", "[options]")
{
  cxxopts::Options options("parses_floats", "parses floats correctly");
  options.add_options()
    ("double", "Double precision", cxxopts::value<double>())
    ("positional", "Floats", cxxopts::value<std::vector<float>>());

  Argv av({"floats", "--double", "0.5", "--", "4", "-4", "1.5e6", "-1.5e6"});

  char** argv = av.argv();
  auto argc = av.argc();

  options.parse_positional("positional");
  auto result = options.parse(argc, argv);

  REQUIRE(result.count("double") == 1);
  REQUIRE(result.count("positional") == 4);

  CHECK(result["double"].as<double>() == 0.5);

  auto& positional = result["positional"].as<std::vector<float>>();
  CHECK(positional[0] == 4);
  CHECK(positional[1] == -4);
  CHECK(positional[2] == 1.5e6);
  CHECK(positional[3] == -1.5e6);
}

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2015 WxMaper (http://wxmaper.ru)
**
** This file is part of the PHPQt5.
**
** BEGIN LICENSE: MPL 2.0
**
** This Source Code Form is subject to the terms of the Mozilla Public
** License, v. 2.0. If a copy of the MPL was not distributed with this
** file, You can obtain one at http://mozilla.org/MPL/2.0/.
**
** END LICENSE
**
****************************************************************************/

#include "phpqt5.h"
#include "pqengine_private.h"

#include "php_streams.h"

zend_object_handlers PHPQt5::pqobject_handlers;

php_stream_ops php_stream_qrc_ops = {
    PHPQt5::php_qrc_write,
    PHPQt5::php_qrc_read,
    PHPQt5::php_qrc_close,
    PHPQt5::php_qrc_flush,
    "qrc",
    NULL,
    NULL,
    NULL,
    NULL
};

php_stream_wrapper_ops php_stream_qrc_wops = {
    PHPQt5::qrc_opener,
    NULL,
    NULL,
    NULL,
    NULL,
    "qrc wrapper",
    NULL,
    NULL,
    NULL,
    NULL
};

static php_stream_wrapper php_qrc_stream_wrapper = {
    &php_stream_qrc_wops,
    NULL,
    0
};

php_stream *PHPQt5::qrc_opener(php_stream_wrapper *wrapper,
                               const char *path,
                               const char *mode,
                               int options,
                               zend_string **opened_path,
                               php_stream_context *context)
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
    PQDBGLPUP(path);
#endif

    QString resourcePath = QString(path).mid(6);
    QByteArray qrc_data;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("open resource");
    #endif

    // QString rFilePath = QString(":/%1/%2").arg(getCorename().constData()).arg(resourcePath);
    QString rFilePath = QString(":/%1").arg(resourcePath);

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP(QString("rFilePath: %1").arg(rFilePath));
    #endif

    QFile file(rFilePath);
    if(file.open(QIODevice::ReadOnly)) {
        qrc_data = file.readAll();
    }
    else {
        php_error(E_ERROR, QString("Resource not found: %1%2").arg(path).arg(PHP_EOL).toUtf8().constData());
        return nullptr;
    }

    QDataStream *s = new QDataStream(qrc_data);
    php_stream *stream = nullptr;
    struct qrc_stream_data *data;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("emalloc qrc_stream_data");
    #endif

    data = (qrc_stream_data *) emalloc(sizeof(*data));
    data->qrc_file = s;
    data->stream = stream;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("php_stream_alloc");
    #endif

    stream = php_stream_alloc(&php_stream_qrc_ops, data, NULL, mode);

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("done");
    #endif

    PQDBG_LVL_DONE();
    return stream;
}

size_t PHPQt5::php_qrc_write(php_stream *stream, const char *buf, size_t count)
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
    PQDBG_LVL_DONE();
#endif

    php_error(E_ERROR, QString("Unable to write to resource file!").toUtf8().constData());

    return 0;
}

int PHPQt5::php_qrc_flush(php_stream *stream)
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
    PQDBG_LVL_DONE();
#endif

    return 0;
}

int PHPQt5::php_qrc_close(php_stream *stream, int close_handle)
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
#endif

    struct qrc_stream_data *self = (struct qrc_stream_data *) stream->abstract;
    int ret = EOF;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("close device");
    #endif

    self->qrc_file->device()->close();
    delete self->qrc_file;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("free stream");
    #endif

    efree(self);

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("done");
    #endif

    PQDBG_LVL_DONE();
    return ret;
}

size_t PHPQt5::php_qrc_read(php_stream *stream, char *buf, size_t count)
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
#endif

    struct qrc_stream_data *self = (struct qrc_stream_data *) stream->abstract;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("read device");
    #endif

    QDataStream *s = self->qrc_file;
    size_t read_bytes = s->device()->read(buf, count);

    stream->eof = 1;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("done");
    #endif

    PQDBG_LVL_DONE();
    return read_bytes;
}

int PHPQt5::zm_startup_phpqt5(INIT_FUNC_ARGS)
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
#endif

    qRegisterMetaType<zval>("zval");
    qRegisterMetaType<zval*>("zval*");

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("register stream wrapper");
    #endif
    php_register_url_stream_wrapper("qrc", &php_qrc_stream_wrapper);

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("register handlers");
    #endif
    memcpy(&pqobject_handlers,
           zend_get_std_object_handlers(),
           sizeof(zend_object_handlers));

    pqobject_handlers.offset = XtOffsetOf(PQObjectWrapper, zo);

    pqobject_handlers.free_obj = pqobject_free_storage;
    pqobject_handlers.call_method = pqobject_call_method;
    pqobject_handlers.get_method = pqobject_get_method;
    pqobject_handlers.clone_obj = NULL;

   // pqobject_handlers.get_property_ptr_ptr = pqobject_get_property_ptr_ptr;

   // pqobject_handlers.get_properties = pqobject_get_properties;
   // pqobject_handlers.read_property	= pqobject_read_property;
   // pqobject_handlers.has_property	= pqobject_has_property;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("register extensions");
    #endif
    PQEnginePrivate::pq_register_extensions(PQDBG_LVL_C);
    phpqt5Connections = new PHPQt5Connection(PQDBG_LVL_C);

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("done");
    #endif

    PQDBG_LVL_DONE();
    return SUCCESS;
}

<commit_msg>Add error handler function<commit_after>/****************************************************************************
**
** Copyright (C) 2015 WxMaper (http://wxmaper.ru)
**
** This file is part of the PHPQt5.
**
** BEGIN LICENSE: MPL 2.0
**
** This Source Code Form is subject to the terms of the Mozilla Public
** License, v. 2.0. If a copy of the MPL was not distributed with this
** file, You can obtain one at http://mozilla.org/MPL/2.0/.
**
** END LICENSE
**
****************************************************************************/

#include "phpqt5.h"
#include "pqengine_private.h"

#include "php_streams.h"

zend_object_handlers PHPQt5::pqobject_handlers;

php_stream_ops php_stream_qrc_ops = {
    PHPQt5::php_qrc_write,
    PHPQt5::php_qrc_read,
    PHPQt5::php_qrc_close,
    PHPQt5::php_qrc_flush,
    "qrc",
    NULL,
    NULL,
    NULL,
    NULL
};

php_stream_wrapper_ops php_stream_qrc_wops = {
    PHPQt5::qrc_opener,
    NULL,
    NULL,
    NULL,
    NULL,
    "qrc wrapper",
    NULL,
    NULL,
    NULL,
    NULL
};

static php_stream_wrapper php_qrc_stream_wrapper = {
    &php_stream_qrc_wops,
    NULL,
    0
};

php_stream *PHPQt5::qrc_opener(php_stream_wrapper *wrapper,
                               const char *path,
                               const char *mode,
                               int options,
                               zend_string **opened_path,
                               php_stream_context *context)
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
    PQDBGLPUP(path);
#endif

    QString resourcePath = QString(path).mid(6);
    QByteArray qrc_data;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("open resource");
    #endif

    // QString rFilePath = QString(":/%1/%2").arg(getCorename().constData()).arg(resourcePath);
    QString rFilePath = QString(":/%1").arg(resourcePath);

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP(QString("rFilePath: %1").arg(rFilePath));
    #endif

    QFile file(rFilePath);
    if(file.open(QIODevice::ReadOnly)) {
        qrc_data = file.readAll();
    }
    else {
        php_error(E_ERROR, QString("Resource not found: %1%2").arg(path).arg(PHP_EOL).toUtf8().constData());
        return nullptr;
    }

    QDataStream *s = new QDataStream(qrc_data);
    php_stream *stream = nullptr;
    struct qrc_stream_data *data;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("emalloc qrc_stream_data");
    #endif

    data = (qrc_stream_data *) emalloc(sizeof(*data));
    data->qrc_file = s;
    data->stream = stream;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("php_stream_alloc");
    #endif

    stream = php_stream_alloc(&php_stream_qrc_ops, data, NULL, mode);

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("done");
    #endif

    PQDBG_LVL_DONE();
    return stream;
}

size_t PHPQt5::php_qrc_write(php_stream *stream, const char *buf, size_t count)
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
    PQDBG_LVL_DONE();
#endif

    php_error(E_ERROR, QString("Unable to write to resource file!").toUtf8().constData());

    return 0;
}

int PHPQt5::php_qrc_flush(php_stream *stream)
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
    PQDBG_LVL_DONE();
#endif

    return 0;
}

int PHPQt5::php_qrc_close(php_stream *stream, int close_handle)
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
#endif

    struct qrc_stream_data *self = (struct qrc_stream_data *) stream->abstract;
    int ret = EOF;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("close device");
    #endif

    self->qrc_file->device()->close();
    delete self->qrc_file;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("free stream");
    #endif

    efree(self);

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("done");
    #endif

    PQDBG_LVL_DONE();
    return ret;
}

size_t PHPQt5::php_qrc_read(php_stream *stream, char *buf, size_t count)
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
#endif

    struct qrc_stream_data *self = (struct qrc_stream_data *) stream->abstract;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("read device");
    #endif

    QDataStream *s = self->qrc_file;
    size_t read_bytes = s->device()->read(buf, count);

    stream->eof = 1;

    #if defined(PQDEBUG) && defined(PQDETAILEDDEBUG)
    PQDBGLPUP("done");
    #endif

    PQDBG_LVL_DONE();
    return read_bytes;
}

static void phpqt5_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args) {
    QString error_type;

    switch(error_num) {
    case E_ERROR: error_type = "Error"; break;
    case E_WARNING: error_type = "Warning"; break;
    case E_CORE_ERROR: error_type = "Core Error"; break;
    case E_CORE_WARNING: error_type = "Core Warning"; break;
    case E_COMPILE_ERROR: error_type = "Compile Error"; break;
    case E_COMPILE_WARNING: error_type = "Compile Warning"; break;
    case E_USER_ERROR: error_type = "User Error"; break;
    case E_USER_WARNING: error_type = "User Warning"; break;
    case E_RECOVERABLE_ERROR: error_type = "Recoverable Error"; break;
    default: return;
    }

    pq_pre(QString("%1: %2 in %3 on line %4")
           .arg(error_type)
           .arg(format)
           .arg(error_filename)
           .arg(error_lineno),
           error_type);
}

int PHPQt5::zm_startup_phpqt5(INIT_FUNC_ARGS)
{
#ifdef PQDEBUG
    PQDBG_LVL_START(__FUNCTION__);
#endif

    zend_error_cb = phpqt5_error_handler; //

    qRegisterMetaType<zval>("zval");
    qRegisterMetaType<zval*>("zval*");

    PQDBGLPUP("register stream wrapper");
    php_register_url_stream_wrapper("qrc", &php_qrc_stream_wrapper);

    PQDBGLPUP("register handlers");
    memcpy(&pqobject_handlers,
    zend_get_std_object_handlers(),
    sizeof(zend_object_handlers));

    pqobject_handlers.offset = XtOffsetOf(PQObjectWrapper, zo);

    pqobject_handlers.free_obj = pqobject_free_storage;
    pqobject_handlers.call_method = pqobject_call_method;
    pqobject_handlers.get_method = pqobject_get_method;
    pqobject_handlers.clone_obj = NULL;

   // pqobject_handlers.get_property_ptr_ptr = pqobject_get_property_ptr_ptr;

   // pqobject_handlers.get_properties = pqobject_get_properties;
   // pqobject_handlers.read_property	= pqobject_read_property;
   // pqobject_handlers.has_property	= pqobject_has_property;

    PQDBGLPUP("register extensions");
    PQEnginePrivate::pq_register_extensions(PQDBG_LVL_C);
    phpqt5Connections = new PHPQt5Connection(PQDBG_LVL_C);

    PQDBG_LVL_DONE_LPUP();
    return SUCCESS;
}

<|endoftext|>


<commit_before>/*
For more information, please see: http://software.sci.utah.edu

The MIT License

Copyright (c) 2015 Scientific Computing and Imaging Institute,
University of Utah.

License for the specific language governing rights and limitations under
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

#include <Core/ConsoleApplication/ConsoleCommands.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <Dataflow/Engine/Controller/NetworkEditorController.h>
#include <Core/Application/Application.h>
#include <Dataflow/Serialization/Network/XMLSerializer.h>
#include <Dataflow/Serialization/Network/NetworkDescriptionSerialization.h>
#include <Dataflow/Network/Module.h>
#include <Core/Logging/ConsoleLogger.h>
#include <Core/Python/PythonInterpreter.h>
#include <boost/algorithm/string.hpp>

using namespace SCIRun::Core;
using namespace Commands;
using namespace Console;
using namespace SCIRun::Dataflow::Networks;
using namespace Algorithms;

LoadFileCommandConsole::LoadFileCommandConsole()
{
  addParameter(Name("FileNum"), 0);
}

//TODO: find a better place for this function
namespace
{
  void quietModulesIfNotVerbose()
  {
    if (!Application::Instance().parameters()->verboseMode())
      Module::defaultLogger_.reset(new SCIRun::Core::Logging::NullLogger);
  }
}

bool LoadFileCommandConsole::execute()
{
  quietModulesIfNotVerbose();

  auto inputFiles = Application::Instance().parameters()->inputFiles();
  std::string filename;
  if (!inputFiles.empty())
    filename = inputFiles[0];
  else
  {
    filename = get(Variables::Filename).toFilename().string();
  }

  /// @todo: real logger
  std::cout << "Attempting load of " << filename << std::endl;
  if (!boost::filesystem::exists(filename))
  {
    std::cout << "File does not exist: " << filename << std::endl;
    return false;
  }
  try
  {
    auto openedFile = XMLSerializer::load_xml<NetworkFile>(filename);

    if (openedFile)
    {
      Application::Instance().controller()->clear();
      Application::Instance().controller()->loadNetwork(openedFile);
      /// @todo: real logger
      std::cout << "File load done: " << filename << std::endl;
      return true;
    }
    /// @todo: real logger
    std::cout << "File load failed: " << filename << std::endl;
  }
  catch (...)
  {
    /// @todo: real logger
    std::cout << "File load failed: " << filename << std::endl;
  }
  return false;
}

bool SaveFileCommandConsole::execute()
{
  return !saveImpl(get(Variables::Filename).toFilename().string()).empty();
}

bool ExecuteCurrentNetworkCommandConsole::execute()
{
  std::cout << "....Executing network..." << std::endl;
  Application::Instance().controller()->connectNetworkExecutionFinished([](int code){ std::cout << "Execution finished with code " << code << std::endl; });
  Application::Instance().controller()->stopExecutionContextLoopWhenExecutionFinishes();
  auto t = Application::Instance().controller()->executeAll(nullptr);
  std::cout << "....Execute started..." << std::endl;
  t->join();
  std::cout << "....Execute thread stopped...entering interactive mode." << std::endl;

  InteractiveModeCommandConsole interactive;
  return interactive.execute();
}

QuitAfterExecuteCommandConsole::QuitAfterExecuteCommandConsole()
{
  addParameter(Name("RunningPython"), false);
}

bool QuitAfterExecuteCommandConsole::execute()
{
  std::cout << "Quit after execute is set." << std::endl;
  Application::Instance().controller()->connectNetworkExecutionFinished([](int code){ exit(code); });
  return true;
}

QuitCommandConsole::QuitCommandConsole()
{
  addParameter(Name("RunningPython"), false);
}

bool QuitCommandConsole::execute()
{
  std::cout << "Goodbye!" << std::endl;
  exit(0);
  return true;
}

bool PrintHelpCommand::execute()
{
  std::cout << Application::Instance().commandHelpString() << std::endl;
  return true;
}

bool PrintVersionCommand::execute()
{
  std::cout << Application::Instance().version() << std::endl;
  return true;
}

bool PrintModulesCommand::execute()
{
  std::cout << "MODULE LIST as of " << Application::Instance().version() << "\n" << Application::Instance().moduleList() << std::endl;
  return true;
}

bool InteractiveModeCommandConsole::execute()
{
#ifdef BUILD_WITH_PYTHON
  quietModulesIfNotVerbose();
  PythonInterpreter::Instance().run_string("import SCIRunPythonAPI; from SCIRunPythonAPI import *");
  std::string line;

  while (true)
  {
    std::cout << "scirun5> " << std::flush;
    std::getline(std::cin, line);
    if (line == "quit") // TODO: need fix for ^D entry || (!x.empty() && x[0] == '\004'))
      break;
    if (std::cin.eof())
      break;
    if (!PythonInterpreter::Instance().run_string(line))
      break;
  }
  std::cout << "\nGoodbye!" << std::endl;
  exit(0);
#endif
  return true;
}

bool RunPythonScriptCommandConsole::execute()
{
  quietModulesIfNotVerbose();

  auto script = Application::Instance().parameters()->pythonScriptFile();
  if (script)
  {
#ifdef BUILD_WITH_PYTHON
    std::cout << "RUNNING PYTHON SCRIPT: " << *script << std::endl;;

    Application::Instance().controller()->clear();
    PythonInterpreter::Instance().run_string("import SCIRunPythonAPI; from SCIRunPythonAPI import *");
    PythonInterpreter::Instance().run_file(script->string());

    //TODO: not sure what else to do here. Probably wait on a condition variable, or just loop forever
    if (!Application::Instance().parameters()->interactiveMode())
    {
      while (true)
      {
        std::cout << "Running Python script." << std::endl;
        boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
      }
    }
    std::cout << "Done running Python script." << std::endl;
    return true;
#else
    std::cout << "Python disabled, cannot run script " << *script << std::endl;
    return false;
#endif
  }
  return false;
}
<commit_msg>Clean up logging.<commit_after>/*
For more information, please see: http://software.sci.utah.edu

The MIT License

Copyright (c) 2015 Scientific Computing and Imaging Institute,
University of Utah.

License for the specific language governing rights and limitations under
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

#include <Core/ConsoleApplication/ConsoleCommands.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <Dataflow/Engine/Controller/NetworkEditorController.h>
#include <Core/Application/Application.h>
#include <Dataflow/Serialization/Network/XMLSerializer.h>
#include <Dataflow/Serialization/Network/NetworkDescriptionSerialization.h>
#include <Dataflow/Network/Module.h>
#include <Core/Logging/ConsoleLogger.h>
#include <Core/Python/PythonInterpreter.h>
#include <boost/algorithm/string.hpp>

using namespace SCIRun::Core;
using namespace Commands;
using namespace Console;
using namespace SCIRun::Dataflow::Networks;
using namespace Algorithms;

LoadFileCommandConsole::LoadFileCommandConsole()
{
  addParameter(Name("FileNum"), 0);
}

//TODO: find a better place for this function
namespace
{
  void quietModulesIfNotVerbose()
  {
    if (!Application::Instance().parameters()->verboseMode())
      Module::defaultLogger_.reset(new SCIRun::Core::Logging::NullLogger);
  }
}

/// @todo: real logger
#define LOG_CONSOLE(x) std::cout << "[SCIRun] " << x << std::endl;

bool LoadFileCommandConsole::execute()
{
  quietModulesIfNotVerbose();

  auto inputFiles = Application::Instance().parameters()->inputFiles();
  std::string filename;
  if (!inputFiles.empty())
    filename = inputFiles[0];
  else
  {
    filename = get(Variables::Filename).toFilename().string();
  }

  LOG_CONSOLE("Attempting load of " << filename);
  if (!boost::filesystem::exists(filename))
  {
    LOG_CONSOLE("File does not exist: " << filename);
    return false;
  }
  try
  {
    auto openedFile = XMLSerializer::load_xml<NetworkFile>(filename);

    if (openedFile)
    {
      Application::Instance().controller()->clear();
      Application::Instance().controller()->loadNetwork(openedFile);
      LOG_CONSOLE("File load done: " << filename);
      return true;
    }
    LOG_CONSOLE("File load failed: " << filename);
  }
  catch (...)
  {
    LOG_CONSOLE("File load failed: " << filename);
  }
  return false;
}

bool SaveFileCommandConsole::execute()
{
  return !saveImpl(get(Variables::Filename).toFilename().string()).empty();
}

bool ExecuteCurrentNetworkCommandConsole::execute()
{
  LOG_CONSOLE("Executing network...");
  Application::Instance().controller()->connectNetworkExecutionFinished([](int code){ LOG_CONSOLE("Execution finished with code " << code); });
  Application::Instance().controller()->stopExecutionContextLoopWhenExecutionFinishes();
  auto t = Application::Instance().controller()->executeAll(nullptr);
  LOG_CONSOLE("Execution started.");
  t->join();
  LOG_CONSOLE("Execute thread stopped. Entering interactive mode.");

  InteractiveModeCommandConsole interactive;
  return interactive.execute();
}

QuitAfterExecuteCommandConsole::QuitAfterExecuteCommandConsole()
{
  addParameter(Name("RunningPython"), false);
}

bool QuitAfterExecuteCommandConsole::execute()
{
  LOG_CONSOLE("Quit after execute is set.");
  Application::Instance().controller()->connectNetworkExecutionFinished([](int code)
  {
    LOG_CONSOLE("Goodbye! Exit code: " << code);
    exit(code);
  });
  return true;
}

QuitCommandConsole::QuitCommandConsole()
{
  addParameter(Name("RunningPython"), false);
}

bool QuitCommandConsole::execute()
{
  LOG_CONSOLE("Goodbye!");
  exit(0);
  return true;
}

bool PrintHelpCommand::execute()
{
  std::cout << Application::Instance().commandHelpString() << std::endl;
  return true;
}

bool PrintVersionCommand::execute()
{
  std::cout << Application::Instance().version() << std::endl;
  return true;
}

bool PrintModulesCommand::execute()
{
  std::cout << "MODULE LIST as of " << Application::Instance().version() << "\n" << Application::Instance().moduleList() << std::endl;
  return true;
}

bool InteractiveModeCommandConsole::execute()
{
#ifdef BUILD_WITH_PYTHON
  quietModulesIfNotVerbose();
  PythonInterpreter::Instance().run_string("import SCIRunPythonAPI; from SCIRunPythonAPI import *");
  std::string line;

  while (true)
  {
    std::cout << "scirun5> " << std::flush;
    std::getline(std::cin, line);
    if (line == "quit") // TODO: need fix for ^D entry || (!x.empty() && x[0] == '\004'))
      break;
    if (std::cin.eof())
      break;
    if (!PythonInterpreter::Instance().run_string(line))
      break;
  }
  std::cout << "\n[SCIRun] Goodbye!" << std::endl;
  exit(0);
#endif
  return true;
}

bool RunPythonScriptCommandConsole::execute()
{
  quietModulesIfNotVerbose();

  auto script = Application::Instance().parameters()->pythonScriptFile();
  if (script)
  {
#ifdef BUILD_WITH_PYTHON
    LOG_CONSOLE("RUNNING PYTHON SCRIPT: " << *script);

    Application::Instance().controller()->clear();
    PythonInterpreter::Instance().run_string("import SCIRunPythonAPI; from SCIRunPythonAPI import *");
    PythonInterpreter::Instance().run_file(script->string());

    //TODO: not sure what else to do here. Probably wait on a condition variable, or just loop forever
    if (!Application::Instance().parameters()->interactiveMode())
    {
      while (true)
      {
        LOG_CONSOLE("Running Python script.");
        boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
      }
    }
    LOG_CONSOLE("Done running Python script.");
    return true;
#else
    LOG_CONSOLE("Python disabled, cannot run script " << *script);
    return false;
#endif
  }
  return false;
}
<|endoftext|>


<commit_before>// RUN: %clangxx_asan -fexceptions -O %s -o %t && %run %t
//
// FIXME: Needs better C++ exception support
// XFAIL: win32
//
// Test __sanitizer_annotate_contiguous_container.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <sanitizer/asan_interface.h>

void TestContainer(size_t capacity) {
  char *beg = new char[capacity];
  char *end = beg + capacity;
  char *mid = beg + capacity;
  char *old_mid = 0;

  for (int i = 0; i < 10000; i++) {
    size_t size = rand() % (capacity + 1);
    assert(size <= capacity);
    old_mid = mid;
    mid = beg + size;
    __sanitizer_annotate_contiguous_container(beg, end, old_mid, mid);

    for (size_t idx = 0; idx < size; idx++)
        assert(!__asan_address_is_poisoned(beg + idx));
    for (size_t idx = size; idx < capacity; idx++)
        assert(__asan_address_is_poisoned(beg + idx));
    assert(__sanitizer_verify_contiguous_container(beg, mid, end));
    if (mid != beg)
      assert(!__sanitizer_verify_contiguous_container(beg, mid - 1, end));
    if (mid != end)
      assert(!__sanitizer_verify_contiguous_container(beg, mid + 1, end));
  }

  // Don't forget to unpoison the whole thing before destroing/reallocating.
  __sanitizer_annotate_contiguous_container(beg, end, mid, end);
  for (size_t idx = 0; idx < capacity; idx++)
    assert(!__asan_address_is_poisoned(beg + idx));
  delete[] beg;
}

__attribute__((noinline))
void Throw() { throw 1; }

__attribute__((noinline))
void ThrowAndCatch() {
  try {
    Throw();
  } catch(...) {
  }
}

void TestThrow() {
  char x[32];
  __sanitizer_annotate_contiguous_container(x, x + 32, x + 32, x + 14);
  assert(!__asan_address_is_poisoned(x + 13));
  assert(__asan_address_is_poisoned(x + 14));
  ThrowAndCatch();
  assert(!__asan_address_is_poisoned(x + 13));
  // FIXME: invert the assertion below once we fix
  // https://code.google.com/p/address-sanitizer/issues/detail?id=258
  // This assertion works only w/o UAR.
  if (!__asan_get_current_fake_stack())
    assert(!__asan_address_is_poisoned(x + 14));
  __sanitizer_annotate_contiguous_container(x, x + 32, x + 14, x + 32);
  assert(!__asan_address_is_poisoned(x + 13));
  assert(!__asan_address_is_poisoned(x + 14));
}

int main(int argc, char **argv) {
  int n = argc == 1 ? 128 : atoi(argv[1]);
  for (int i = 0; i <= n; i++)
    TestContainer(i);
  TestThrow();
}
<commit_msg>Remove the XFAIL for the C++ EH test<commit_after>// RUN: %clangxx_asan -fexceptions -O %s -o %t && %run %t
//
// Test __sanitizer_annotate_contiguous_container.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <sanitizer/asan_interface.h>

void TestContainer(size_t capacity) {
  char *beg = new char[capacity];
  char *end = beg + capacity;
  char *mid = beg + capacity;
  char *old_mid = 0;

  for (int i = 0; i < 10000; i++) {
    size_t size = rand() % (capacity + 1);
    assert(size <= capacity);
    old_mid = mid;
    mid = beg + size;
    __sanitizer_annotate_contiguous_container(beg, end, old_mid, mid);

    for (size_t idx = 0; idx < size; idx++)
        assert(!__asan_address_is_poisoned(beg + idx));
    for (size_t idx = size; idx < capacity; idx++)
        assert(__asan_address_is_poisoned(beg + idx));
    assert(__sanitizer_verify_contiguous_container(beg, mid, end));
    if (mid != beg)
      assert(!__sanitizer_verify_contiguous_container(beg, mid - 1, end));
    if (mid != end)
      assert(!__sanitizer_verify_contiguous_container(beg, mid + 1, end));
  }

  // Don't forget to unpoison the whole thing before destroing/reallocating.
  __sanitizer_annotate_contiguous_container(beg, end, mid, end);
  for (size_t idx = 0; idx < capacity; idx++)
    assert(!__asan_address_is_poisoned(beg + idx));
  delete[] beg;
}

__attribute__((noinline))
void Throw() { throw 1; }

__attribute__((noinline))
void ThrowAndCatch() {
  try {
    Throw();
  } catch(...) {
  }
}

void TestThrow() {
  char x[32];
  __sanitizer_annotate_contiguous_container(x, x + 32, x + 32, x + 14);
  assert(!__asan_address_is_poisoned(x + 13));
  assert(__asan_address_is_poisoned(x + 14));
  ThrowAndCatch();
  assert(!__asan_address_is_poisoned(x + 13));
  // FIXME: invert the assertion below once we fix
  // https://code.google.com/p/address-sanitizer/issues/detail?id=258
  // This assertion works only w/o UAR.
  if (!__asan_get_current_fake_stack())
    assert(!__asan_address_is_poisoned(x + 14));
  __sanitizer_annotate_contiguous_container(x, x + 32, x + 14, x + 32);
  assert(!__asan_address_is_poisoned(x + 13));
  assert(!__asan_address_is_poisoned(x + 14));
}

int main(int argc, char **argv) {
  int n = argc == 1 ? 128 : atoi(argv[1]);
  for (int i = 0; i <= n; i++)
    TestContainer(i);
  TestThrow();
}
<|endoftext|>


<commit_before>/*
 * Copyright 2010 MQWeb - Franky Braem
 *
 * Licensed under the EUPL, Version 1.1 or – as soon they
 * will be approved by the European Commission - subsequent
 * versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the
 * Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://joinup.ec.europa.eu/software/page/eupl
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the Licence is
 * distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the Licence for the specific language governing
 * permissions and limitations under the Licence.
 */
#include <sstream>

#include <MQ/Web/QueueManagerController.h>
#include <MQ/Web/QueueManagerMapper.h>

namespace MQ
{
namespace Web
{

QueueManagerController::QueueManagerController() : MQController()
{
}

QueueManagerController::~QueueManagerController()
{
}

void QueueManagerController::view()
{
	QueueManagerMapper queueManagerMapper(*commandServer());

	Poco::JSON::Object::Ptr dummyFilter = new Poco::JSON::Object();
	Poco::JSON::Array::Ptr jsonQueueManagers = queueManagerMapper.inquire(dummyFilter);

	if ( jsonQueueManagers->size() > 0 )
	{
		set("qmgr", jsonQueueManagers->get(0));
		render("home.tpl");
	}
}

} } // Namespace MQ::Web
<commit_msg>Check the format and return JSON or HTML<commit_after>/*
 * Copyright 2010 MQWeb - Franky Braem
 *
 * Licensed under the EUPL, Version 1.1 or – as soon they
 * will be approved by the European Commission - subsequent
 * versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the
 * Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://joinup.ec.europa.eu/software/page/eupl
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the Licence is
 * distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the Licence for the specific language governing
 * permissions and limitations under the Licence.
 */
#include <sstream>

#include <MQ/Web/QueueManagerController.h>
#include <MQ/Web/QueueManagerMapper.h>

namespace MQ
{
namespace Web
{

QueueManagerController::QueueManagerController() : MQController()
{
}

QueueManagerController::~QueueManagerController()
{
}

void QueueManagerController::view()
{
	QueueManagerMapper queueManagerMapper(*commandServer());

	Poco::JSON::Object::Ptr dummyFilter = new Poco::JSON::Object();
	Poco::JSON::Array::Ptr jsonQueueManagers = queueManagerMapper.inquire(dummyFilter);

	if ( jsonQueueManagers->size() > 0 )
	{
		set("qmgr", jsonQueueManagers->get(0));
		if ( format().compare("html") == 0 )
		{
			render("home.tpl");
		}
		else if ( format().compare("json") == 0 )
		{
			data().stringify(response().send());
		}
	}
}

} } // Namespace MQ::Web
<|endoftext|>


<commit_before>#include "Common/HighQueuePch.h"
#define BOOST_TEST_NO_MAIN HighQueuePerformanceTest
#include <boost/test/unit_test.hpp>

#include <HighQueue/Producer.h>
#include <HighQueue/Consumer.h>
#include <Common/Stopwatch.h>
#include <HQPerformance/TestMessage.h>

using namespace HighQueue;
typedef TestMessage<20> ActualMessage;

namespace
{
    volatile std::atomic<uint32_t> threadsReady;
    volatile bool producerGo = false;

    void producerFunction(Connection & connection, uint32_t producerNumber, uint64_t messageCount, bool solo)
    {
        Producer producer(connection, solo);
        HighQueue::Message producerMessage;
        if(!connection.allocate(producerMessage))
        {
            std::cerr << "Failed to allocate message for producer Number " << producerNumber << std::endl;
            return;
        }

        ++threadsReady;
        while(!producerGo)
        {
            std::this_thread::yield();
        }

        for(uint32_t messageNumber = 0; messageNumber < messageCount; ++messageNumber)
        {
            auto testMessage = producerMessage.construct<ActualMessage>(producerNumber, messageNumber);
            producer.publish(producerMessage);
        }
    }
}

#define DISABLE_MultithreadMessagePassingPerformancex
#ifdef DISABLE_MultithreadMessagePassingPerformance
#pragma message ("DISABLE_MultithreadMessagePassingPerformance")
#else // DISABLE_MultithreadMessagePassingPerformance
BOOST_AUTO_TEST_CASE(testMultithreadMessagePassingPerformance)
{
    static const size_t entryCount = 100000;
    static const size_t messageSize = sizeof(ActualMessage);

    static const uint64_t targetMessageCount = 1000000 * 100; // runs about 5 to 10 seconds in release/optimized build
    static const size_t producerLimit = 2;//10; // running on 8 core system.  Once we go over 7 producers it slows down.  That's one thing we want to see.
    static const size_t consumerLimit = 1;  // Just for documentation
    static const size_t messageCount = entryCount + consumerLimit +  producerLimit;

    static const size_t spinCount = 0;
    static const size_t yieldCount = ConsumerWaitStrategy::FOREVER;

    ConsumerWaitStrategy strategy(spinCount, yieldCount);
    CreationParameters parameters(strategy, entryCount, messageSize, messageCount);
    Connection connection;
    connection.createLocal("LocalIv", parameters);

    Consumer consumer(connection);
    HighQueue::Message consumerMessage;
    BOOST_REQUIRE(connection.allocate(consumerMessage));

    for(size_t producerCount = 1; producerCount < producerLimit; ++producerCount)
    {
        std::cerr << "Test " << producerCount << " producer";

        std::vector<std::thread> producerThreads;
        std::vector<uint64_t> nextMessage;

        threadsReady = 0;
        producerGo = false;
        size_t perProducer = targetMessageCount / producerCount;
        size_t actualMessageCount = perProducer * producerCount;

        for(uint32_t nTh = 0; nTh < producerCount; ++nTh)
        {
            nextMessage.emplace_back(0u);
            producerThreads.emplace_back(
                std::bind(producerFunction, std::ref(connection), nTh, perProducer, producerCount == 1));
        }
        std::this_thread::yield();

        while(threadsReady < producerCount)
        {
            std::this_thread::yield();
        }

        Stopwatch timer;
        producerGo = true;

        for(uint64_t messageNumber = 0; messageNumber < actualMessageCount; ++messageNumber)
        {
            consumer.getNext(consumerMessage);
            auto testMessage = consumerMessage.get<ActualMessage>();
            testMessage->touch();
            auto & msgNumber = nextMessage[testMessage->producerNumber()];
            if(msgNumber != testMessage->messageNumber())
            {
                // the if avoids the performance hit of BOOST_CHECK_EQUAL unless it's needed.
                BOOST_CHECK_EQUAL(messageNumber, testMessage->messageNumber());
            }
            ++ msgNumber;
        }

        auto lapse = timer.nanoseconds();

        // sometimes we synchronize thread shut down.
        producerGo = false;

        for(size_t nTh = 0; nTh < producerCount; ++nTh)
        {
            producerThreads[nTh].join();
        }

        auto messageBytes = sizeof(ActualMessage);
        auto messageBits = sizeof(ActualMessage) * 8;
        std::cout << " Passed " << actualMessageCount << ' ' << messageBytes << " byte messages in "
            << std::setprecision(9) << double(lapse) / double(Stopwatch::nanosecondsPerSecond) << " seconds.  "
            << lapse / actualMessageCount << " nsec./message "
            << std::setprecision(3) << double(actualMessageCount) / double(lapse) << " GMsg/second "
            << std::setprecision(3) << double(actualMessageCount * messageBytes) / double(lapse) << " GByte/second "
            << std::setprecision(3) << double(actualMessageCount * messageBits) / double(lapse) << " GBit/second."
            << std::endl;
    }
}
#endif // DISABLE_MultithreadMessagePassingPerformance
<commit_msg>Re-enable multithread test<commit_after>#include "Common/HighQueuePch.h"
#define BOOST_TEST_NO_MAIN HighQueuePerformanceTest
#include <boost/test/unit_test.hpp>

#include <HighQueue/Producer.h>
#include <HighQueue/Consumer.h>
#include <Common/Stopwatch.h>
#include <HQPerformance/TestMessage.h>

using namespace HighQueue;
typedef TestMessage<20> ActualMessage;

namespace
{
    volatile std::atomic<uint32_t> threadsReady;
    volatile bool producerGo = false;

    void producerFunction(Connection & connection, uint32_t producerNumber, uint64_t messageCount, bool solo)
    {
        Producer producer(connection, solo);
        HighQueue::Message producerMessage;
        if(!connection.allocate(producerMessage))
        {
            std::cerr << "Failed to allocate message for producer Number " << producerNumber << std::endl;
            return;
        }

        ++threadsReady;
        while(!producerGo)
        {
            std::this_thread::yield();
        }

        for(uint32_t messageNumber = 0; messageNumber < messageCount; ++messageNumber)
        {
            auto testMessage = producerMessage.construct<ActualMessage>(producerNumber, messageNumber);
            producer.publish(producerMessage);
        }
    }
}

#define DISABLE_MultithreadMessagePassingPerformancex
#ifdef DISABLE_MultithreadMessagePassingPerformance
#pragma message ("DISABLE_MultithreadMessagePassingPerformance")
#else // DISABLE_MultithreadMessagePassingPerformance
BOOST_AUTO_TEST_CASE(testMultithreadMessagePassingPerformance)
{
    static const size_t entryCount = 100000;
    static const size_t messageSize = sizeof(ActualMessage);

    static const uint64_t targetMessageCount = 1000000 * 100; // runs about 5 to 10 seconds in release/optimized build
    static const size_t producerLimit = 8; // running on 8 core system.  Once we go over 7 producers it slows down.  That's one thing we want to see.
    static const size_t consumerLimit = 1;  // Just for documentation
    static const size_t messageCount = entryCount + consumerLimit +  producerLimit;

    static const size_t spinCount = 0;
    static const size_t yieldCount = ConsumerWaitStrategy::FOREVER;

    ConsumerWaitStrategy strategy(spinCount, yieldCount);
    CreationParameters parameters(strategy, entryCount, messageSize, messageCount);
    Connection connection;
    connection.createLocal("LocalIv", parameters);

    Consumer consumer(connection);
    HighQueue::Message consumerMessage;
    BOOST_REQUIRE(connection.allocate(consumerMessage));

    for(size_t producerCount = 1; producerCount <= producerLimit; ++producerCount)
    {
        std::cerr << "Test " << producerCount << " producer";

        std::vector<std::thread> producerThreads;
        std::vector<uint64_t> nextMessage;

        threadsReady = 0;
        producerGo = false;
        size_t perProducer = targetMessageCount / producerCount;
        size_t actualMessageCount = perProducer * producerCount;

        for(uint32_t nTh = 0; nTh < producerCount; ++nTh)
        {
            nextMessage.emplace_back(0u);
            producerThreads.emplace_back(
                std::bind(producerFunction, std::ref(connection), nTh, perProducer, producerCount == 1));
        }
        std::this_thread::yield();

        while(threadsReady < producerCount)
        {
            std::this_thread::yield();
        }

        Stopwatch timer;
        producerGo = true;

        for(uint64_t messageNumber = 0; messageNumber < actualMessageCount; ++messageNumber)
        {
            consumer.getNext(consumerMessage);
            auto testMessage = consumerMessage.get<ActualMessage>();
            testMessage->touch();
            auto & msgNumber = nextMessage[testMessage->producerNumber()];
            if(msgNumber != testMessage->messageNumber())
            {
                // the if avoids the performance hit of BOOST_CHECK_EQUAL unless it's needed.
                BOOST_CHECK_EQUAL(messageNumber, testMessage->messageNumber());
            }
            ++ msgNumber;
        }

        auto lapse = timer.nanoseconds();

        // sometimes we synchronize thread shut down.
        producerGo = false;

        for(size_t nTh = 0; nTh < producerCount; ++nTh)
        {
            producerThreads[nTh].join();
        }

        auto messageBytes = sizeof(ActualMessage);
        auto messageBits = sizeof(ActualMessage) * 8;
        std::cout << " Passed " << actualMessageCount << ' ' << messageBytes << " byte messages in "
            << std::setprecision(9) << double(lapse) / double(Stopwatch::nanosecondsPerSecond) << " seconds.  "
            << lapse / actualMessageCount << " nsec./message "
            << std::setprecision(3) << double(actualMessageCount) / double(lapse) << " GMsg/second "
            << std::setprecision(3) << double(actualMessageCount * messageBytes) / double(lapse) << " GByte/second "
            << std::setprecision(3) << double(actualMessageCount * messageBits) / double(lapse) << " GBit/second."
            << std::endl;
    }
}
#endif // DISABLE_MultithreadMessagePassingPerformance
<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include "MDSMap.h"

#include <sstream>
using std::stringstream;

void MDSMap::print(ostream& out)
{
  out << "epoch " << epoch << std::endl;
  out << "\nclient_epoch " << client_epoch << std::endl;
  out << "created " << created << std::endl;
  out << "tableserver " << tableserver << std::endl;
  out << "root " << root << std::endl;
  out << "session_timeout " << session_timeout << "\n"
      << "session_autoclose " << session_autoclose << "\n";

  out << "\nmax_mds " << max_mds << std::endl;

  set<int> upset;
  get_up_mds_set(upset);
  out << "in " << in << "\n"
      << "up " << upset << "\n";

  multimap< pair<unsigned,unsigned>, entity_addr_t > foo;
  for (map<entity_addr_t,mds_info_t>::iterator p = mds_info.begin();
       p != mds_info.end();
       p++)
    foo.insert(pair<pair<unsigned,unsigned>,entity_addr_t>(pair<unsigned,unsigned>(p->second.mds, p->second.inc-1), p->first));

  for (multimap< pair<unsigned,unsigned>, entity_addr_t >::iterator p = foo.begin();
       p != foo.end();
       p++) {
    mds_info_t& info = mds_info[p->second];

    out << info.addr
	<< " mds" << info.mds
	<< "." << info.inc
	<< " " << get_state_name(info.state)
	<< " seq " << info.state_seq;
    if (info.laggy())
      out << " laggy since " << info.laggy_since;
    out << "\n";
  }

  if (failed.size())
    out << "failed " << failed << "\n";
  if (stopped.size())
    out << "stopped " << failed << "\n";
}

void MDSMap::print_summary(ostream& out)
{
  map<int,int> by_state;
  for (map<entity_addr_t,mds_info_t>::iterator p = mds_info.begin();
       p != mds_info.end();
       p++)
    by_state[p->second.state]++;

  out << "e" << get_epoch() << ": " << up.size() << "/" << in.size() << " up";

  for (map<int,int>::reverse_iterator p = by_state.rbegin(); p != by_state.rend(); p++)
    out << ", " << p->second << " " << get_state_name(p->first);

  if (failed.size())
    out << ", " << failed.size() << " failed";
}
<commit_msg>mds: include max mds in mdsmap summary<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include "MDSMap.h"

#include <sstream>
using std::stringstream;

void MDSMap::print(ostream& out)
{
  out << "epoch " << epoch << std::endl;
  out << "\nclient_epoch " << client_epoch << std::endl;
  out << "created " << created << std::endl;
  out << "tableserver " << tableserver << std::endl;
  out << "root " << root << std::endl;
  out << "session_timeout " << session_timeout << "\n"
      << "session_autoclose " << session_autoclose << "\n";

  out << "\nmax_mds " << max_mds << std::endl;

  set<int> upset;
  get_up_mds_set(upset);
  out << "in " << in << "\n"
      << "up " << upset << "\n";

  multimap< pair<unsigned,unsigned>, entity_addr_t > foo;
  for (map<entity_addr_t,mds_info_t>::iterator p = mds_info.begin();
       p != mds_info.end();
       p++)
    foo.insert(pair<pair<unsigned,unsigned>,entity_addr_t>(pair<unsigned,unsigned>(p->second.mds, p->second.inc-1), p->first));

  for (multimap< pair<unsigned,unsigned>, entity_addr_t >::iterator p = foo.begin();
       p != foo.end();
       p++) {
    mds_info_t& info = mds_info[p->second];

    out << info.addr
	<< " mds" << info.mds
	<< "." << info.inc
	<< " " << get_state_name(info.state)
	<< " seq " << info.state_seq;
    if (info.laggy())
      out << " laggy since " << info.laggy_since;
    out << "\n";
  }

  if (failed.size())
    out << "failed " << failed << "\n";
  if (stopped.size())
    out << "stopped " << failed << "\n";
}

void MDSMap::print_summary(ostream& out)
{
  map<int,int> by_state;
  for (map<entity_addr_t,mds_info_t>::iterator p = mds_info.begin();
       p != mds_info.end();
       p++)
    by_state[p->second.state]++;

  out << "e" << get_epoch() << ": " << up.size() << "/" << in.size() << "/" << max_mds << " up";

  for (map<int,int>::reverse_iterator p = by_state.rbegin(); p != by_state.rend(); p++)
    out << ", " << p->second << " " << get_state_name(p->first);

  if (failed.size())
    out << ", " << failed.size() << " failed";
}
<|endoftext|>