<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstdlib>

#include "MemoryOutputStream.hh"
#include "RLEv1.hh"

#include "wrap/orc-proto-wrapper.hh"
#include "wrap/gtest-wrapper.h"

#ifdef __clang__
  DIAGNOSTIC_IGNORE("-Wmissing-variable-declarations")
#endif

namespace orc {

  using ::testing::TestWithParam;
  using ::testing::Values;

  const int DEFAULT_MEM_STREAM_SIZE = 1024 * 1024; // 1M

  class RleTest : public TestWithParam<bool> {
    virtual void SetUp();

  protected:
    bool alignBitpacking;
    std::unique_ptr<RleEncoder> getEncoder(RleVersion version,
                                           MemoryOutputStream& memStream,
                                           bool isSigned);

    void runExampleTest(int64_t* inputData, uint64_t inputLength,
                        unsigned char* expectedOutput, uint64_t outputLength);

    void runTest(RleVersion version,
                 uint64_t numValues,
                 int64_t start,
                 int64_t delta,
                 bool random,
                 bool isSigned,
                 uint64_t numNulls = 0);
  };

  void RleTest::SetUp() {
    alignBitpacking = GetParam();
  }

  void generateData(
                     uint64_t numValues,
                     int64_t start,
                     int64_t delta,
                     bool random,
                     int64_t* data,
                     uint64_t numNulls = 0,
                     char* notNull = nullptr) {
    if (numNulls != 0 && notNull != nullptr) {
      memset(notNull, 1, numValues);
      while (numNulls > 0) {
        uint64_t pos = static_cast<uint64_t>(std::rand()) % numValues;
        if (notNull[pos]) {
          notNull[pos] = static_cast<char>(0);
          --numNulls;
        }
      }
    }

    for (uint64_t i = 0; i < numValues; ++i) {
      if (notNull == nullptr || notNull[i])
      {
        if (!random) {
          data[i] = start + delta * static_cast<int64_t>(i);
        } else {
          data[i] = std::rand();
        }
      }
    }
  }

  void decodeAndVerify(
                       RleVersion version,
                       const MemoryOutputStream& memStream,
                       int64_t * data,
                       uint64_t numValues,
                       const char* notNull,
                       bool isSinged) {
    std::unique_ptr<RleDecoder> decoder = createRleDecoder(
            std::unique_ptr<SeekableArrayInputStream>(new SeekableArrayInputStream(
                    memStream.getData(),
                    memStream.getLength())),
            isSinged, version, *getDefaultPool());

    int64_t* decodedData = new int64_t[numValues];
    decoder->next(decodedData, numValues, notNull);

    for (uint64_t i = 0; i < numValues; ++i) {
      if (!notNull || notNull[i]) {
        EXPECT_EQ(data[i], decodedData[i]);
      }
    }

    delete [] decodedData;
  }

  std::unique_ptr<RleEncoder> RleTest::getEncoder(RleVersion version,
                                        MemoryOutputStream& memStream,
                                        bool isSigned)
  {
    MemoryPool * pool = getDefaultPool();

    return createRleEncoder(
            std::unique_ptr<BufferedOutputStream>(
                    new BufferedOutputStream(*pool, &memStream, 500 * 1024, 1024)),
            isSigned, version, *pool, alignBitpacking);
  }

  void RleTest::runExampleTest(int64_t* inputData,
                      uint64_t inputLength,
                      unsigned char* expectedOutput,
                      uint64_t outputLength) {
    MemoryOutputStream memStream(DEFAULT_MEM_STREAM_SIZE);

    std::unique_ptr<RleEncoder> encoder = getEncoder(RleVersion_2, memStream, false);

    encoder->add(inputData, inputLength, nullptr);
    encoder->flush();
    const char* output = memStream.getData();
    for(int i = 0; i < outputLength; i++) {
      EXPECT_EQ(expectedOutput[i], static_cast<unsigned char>(output[i]));
    }
  }

  void RleTest::runTest(RleVersion version,
               uint64_t numValues,
               int64_t start,
               int64_t delta,
               bool random,
               bool isSigned,
               uint64_t numNulls) {
    MemoryOutputStream memStream(DEFAULT_MEM_STREAM_SIZE);

    std::unique_ptr<RleEncoder> encoder = getEncoder(version, memStream, isSigned);

    char* notNull = numNulls == 0 ? nullptr : new char[numValues];
    int64_t* data = new int64_t[numValues];
    generateData(numValues, start, delta, random, data, numNulls, notNull);
    encoder->add(data, numValues, notNull);
    encoder->flush();

    decodeAndVerify(version, memStream, data, numValues, notNull, isSigned);
    delete [] data;
    delete [] notNull;
  }

  TEST_P(RleTest, RleV1_delta_increasing_sequance_unsigned) {
    runTest(RleVersion_1, 1024, 0, 1, false, false);
  }

  TEST_P(RleTest, RleV1_delta_increasing_sequance_unsigned_null) {
    runTest(RleVersion_1, 1024, 0, 1, false, false, 100);
  }

  TEST_P(RleTest, RleV1_delta_decreasing_sequance_unsigned) {
    runTest(RleVersion_1, 1024, 5000, -3, false, false);
  }

  TEST_P(RleTest, RleV1_delta_decreasing_sequance_signed) {
    runTest(RleVersion_1, 1024, 100, -3, false, true);
  }

  TEST_P(RleTest, RleV1_delta_decreasing_sequance_signed_null) {
    runTest(RleVersion_1, 1024, 100, -3, false, true, 500);
  }

  TEST_P(RleTest, rRleV1_andom_sequance_signed) {
    runTest(RleVersion_1, 1024, 0, 0, true, true);
  }

  TEST_P(RleTest, RleV1_all_null) {
    runTest(RleVersion_1, 1024, 100, -3, false, true, 1024);
  }

  TEST_P(RleTest, RleV2_delta_increasing_sequance_unsigned) {
    runTest(RleVersion_2, 1024, 0, 1, false, false);
  }

  TEST_P(RleTest, RleV2_delta_increasing_sequance_unsigned_null) {
    runTest(RleVersion_2, 1024, 0, 1, false, false, 100);
  }

  TEST_P(RleTest, RleV2_delta_decreasing_sequance_unsigned) {
    runTest(RleVersion_2, 1024, 5000, -3, false, false);
  }

  TEST_P(RleTest, RleV2_delta_decreasing_sequance_signed) {
    runTest(RleVersion_2, 1024, 100, -3, false, true);
  }

  TEST_P(RleTest, RleV2_delta_decreasing_sequance_signed_null) {
    runTest(RleVersion_2, 1024, 100, -3, false, true, 500);
  }

  TEST_P(RleTest, RleV2_random_sequance_signed) {
    runTest(RleVersion_2, 1024, 0, 0, true, true);
  }

  TEST_P(RleTest, RleV2_all_null) {
    runTest(RleVersion_2, 1024, 100, -3, false, true, 1024);
  }

  TEST_P(RleTest, RleV2_delta_zero_unsigned) {
    runTest(RleVersion_2, 1024, 123, 0, false, false);
  }

  TEST_P(RleTest, RleV2_delta_zero_signed) {
    runTest(RleVersion_2, 1024, 123, 0, false, true);
  }

  TEST_P(RleTest, RleV2_short_repeat) {
    runTest(RleVersion_2, 8, 123, 0, false, false);
  }

  TEST_P(RleTest, RleV2_short_repeat_example) {
    int64_t data[5] = {10000, 10000, 10000, 10000, 10000};
    unsigned char expectedEncoded[3] = {0x0a, 0x27, 0x10};
    runExampleTest(data, 5, expectedEncoded, 3);
  }

  TEST_P(RleTest, RleV2_direct_example) {
    int64_t data[4] = {23713, 43806, 57005, 48879};
    unsigned char expectedEncoded[10] = {0x5e, 0x03, 0x5c, 0xa1, 0xab, 0x1e, 0xde, 0xad, 0xbe, 0xef};
    runExampleTest(data, 4, expectedEncoded, 10);
  }

  TEST_P(RleTest, RleV2_Patched_base_example) {
    int64_t data[20] = {2030, 2000, 2020, 1000000, 2040, 2050, 2060, 2070, 2080,
                        2090, 2100, 2110, 2120, 2130, 2140, 2150, 2160, 2170, 2180, 2190};
    unsigned char expectedEncoded[28] = {0x8e, 0x13, 0x2b, 0x21, 0x07, 0xd0, 0x1e, 0x00, 0x14,
                                0x70, 0x28, 0x32, 0x3c, 0x46, 0x50, 0x5a, 0x64, 0x6e, 0x78, 0x82, 0x8c,
                                0x96, 0xa0, 0xaa, 0xb4, 0xbe, 0xfc, 0xe8};
    runExampleTest(data, 20, expectedEncoded, 28);
  }

  TEST_P(RleTest, RleV2_delta_example) {
    int64_t data[10] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
    unsigned char expectedEncoded[8] = {0xc6, 0x09, 0x02, 0x02, 0x22, 0x42, 0x42, 0x46};
    unsigned char unalignedExpectedEncoded[7] = {0xc4, 0x09, 0x02, 0x02, 0x4A, 0x28, 0xA6};
    if (alignBitpacking)
    {
      runExampleTest(data, 10, expectedEncoded, 8);
    }
    else
    {
      runExampleTest(data, 10, unalignedExpectedEncoded, 7);
    }
  }

  TEST_P(RleTest, RleV2_delta_example2) {
    int64_t data[7] = {0, 10000, 10001, 10001, 10002, 10003, 10003};
    unsigned char expectedEncoded[8] = {0xc2, 0x06, 0x0, 0xa0, 0x9c, 0x01, 0x45, 0x0};
    runExampleTest(data, 7, expectedEncoded, 8);
  }

  TEST_P(RleTest, RleV2_direct_repeat_example2) {
    int64_t data[9] = {23713, 43806, 57005, 48879, 10000, 10000, 10000, 10000, 10000};
    unsigned char expectedEncoded[13] = {0x5e, 0x03, 0x5c, 0xa1, 0xab, 0x1e, 0xde, 0xad, 0xbe, 0xef, 0x0a, 0x27, 0x10};
    runExampleTest(data, 9, expectedEncoded, 13);
  }

  INSTANTIATE_TEST_CASE_P(OrcTest, RleTest, Values(true, false));
}
<commit_msg>ORC-465: [C++] add a test for PATCHED_BASE with a big gap. (#362)<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstdlib>

#include "MemoryOutputStream.hh"
#include "RLEv1.hh"

#include "wrap/orc-proto-wrapper.hh"
#include "wrap/gtest-wrapper.h"

#ifdef __clang__
  DIAGNOSTIC_IGNORE("-Wmissing-variable-declarations")
#endif

namespace orc {

  using ::testing::TestWithParam;
  using ::testing::Values;

  const int DEFAULT_MEM_STREAM_SIZE = 1024 * 1024; // 1M

  class RleTest : public TestWithParam<bool> {
    virtual void SetUp();

  protected:
    bool alignBitpacking;
    std::unique_ptr<RleEncoder> getEncoder(RleVersion version,
                                           MemoryOutputStream& memStream,
                                           bool isSigned);

    void runExampleTest(int64_t* inputData, uint64_t inputLength,
                        unsigned char* expectedOutput, uint64_t outputLength);

    void runTest(RleVersion version,
                 uint64_t numValues,
                 int64_t start,
                 int64_t delta,
                 bool random,
                 bool isSigned,
                 uint64_t numNulls = 0);
  };

  void RleTest::SetUp() {
    alignBitpacking = GetParam();
  }

  void generateData(
                     uint64_t numValues,
                     int64_t start,
                     int64_t delta,
                     bool random,
                     int64_t* data,
                     uint64_t numNulls = 0,
                     char* notNull = nullptr) {
    if (numNulls != 0 && notNull != nullptr) {
      memset(notNull, 1, numValues);
      while (numNulls > 0) {
        uint64_t pos = static_cast<uint64_t>(std::rand()) % numValues;
        if (notNull[pos]) {
          notNull[pos] = static_cast<char>(0);
          --numNulls;
        }
      }
    }

    for (uint64_t i = 0; i < numValues; ++i) {
      if (notNull == nullptr || notNull[i])
      {
        if (!random) {
          data[i] = start + delta * static_cast<int64_t>(i);
        } else {
          data[i] = std::rand();
        }
      }
    }
  }

  void decodeAndVerify(
                       RleVersion version,
                       const MemoryOutputStream& memStream,
                       int64_t * data,
                       uint64_t numValues,
                       const char* notNull,
                       bool isSinged) {
    std::unique_ptr<RleDecoder> decoder = createRleDecoder(
            std::unique_ptr<SeekableArrayInputStream>(new SeekableArrayInputStream(
                    memStream.getData(),
                    memStream.getLength())),
            isSinged, version, *getDefaultPool());

    int64_t* decodedData = new int64_t[numValues];
    decoder->next(decodedData, numValues, notNull);

    for (uint64_t i = 0; i < numValues; ++i) {
      if (!notNull || notNull[i]) {
        EXPECT_EQ(data[i], decodedData[i]);
      }
    }

    delete [] decodedData;
  }

  std::unique_ptr<RleEncoder> RleTest::getEncoder(RleVersion version,
                                        MemoryOutputStream& memStream,
                                        bool isSigned)
  {
    MemoryPool * pool = getDefaultPool();

    return createRleEncoder(
            std::unique_ptr<BufferedOutputStream>(
                    new BufferedOutputStream(*pool, &memStream, 500 * 1024, 1024)),
            isSigned, version, *pool, alignBitpacking);
  }

  void RleTest::runExampleTest(int64_t* inputData,
                      uint64_t inputLength,
                      unsigned char* expectedOutput,
                      uint64_t outputLength) {
    MemoryOutputStream memStream(DEFAULT_MEM_STREAM_SIZE);

    std::unique_ptr<RleEncoder> encoder = getEncoder(RleVersion_2, memStream, false);

    encoder->add(inputData, inputLength, nullptr);
    encoder->flush();
    const char* output = memStream.getData();
    for(int i = 0; i < outputLength; i++) {
      EXPECT_EQ(expectedOutput[i], static_cast<unsigned char>(output[i]));
    }
  }

  void RleTest::runTest(RleVersion version,
               uint64_t numValues,
               int64_t start,
               int64_t delta,
               bool random,
               bool isSigned,
               uint64_t numNulls) {
    MemoryOutputStream memStream(DEFAULT_MEM_STREAM_SIZE);

    std::unique_ptr<RleEncoder> encoder = getEncoder(version, memStream, isSigned);

    char* notNull = numNulls == 0 ? nullptr : new char[numValues];
    int64_t* data = new int64_t[numValues];
    generateData(numValues, start, delta, random, data, numNulls, notNull);
    encoder->add(data, numValues, notNull);
    encoder->flush();

    decodeAndVerify(version, memStream, data, numValues, notNull, isSigned);
    delete [] data;
    delete [] notNull;
  }

  TEST_P(RleTest, RleV1_delta_increasing_sequance_unsigned) {
    runTest(RleVersion_1, 1024, 0, 1, false, false);
  }

  TEST_P(RleTest, RleV1_delta_increasing_sequance_unsigned_null) {
    runTest(RleVersion_1, 1024, 0, 1, false, false, 100);
  }

  TEST_P(RleTest, RleV1_delta_decreasing_sequance_unsigned) {
    runTest(RleVersion_1, 1024, 5000, -3, false, false);
  }

  TEST_P(RleTest, RleV1_delta_decreasing_sequance_signed) {
    runTest(RleVersion_1, 1024, 100, -3, false, true);
  }

  TEST_P(RleTest, RleV1_delta_decreasing_sequance_signed_null) {
    runTest(RleVersion_1, 1024, 100, -3, false, true, 500);
  }

  TEST_P(RleTest, rRleV1_andom_sequance_signed) {
    runTest(RleVersion_1, 1024, 0, 0, true, true);
  }

  TEST_P(RleTest, RleV1_all_null) {
    runTest(RleVersion_1, 1024, 100, -3, false, true, 1024);
  }

  TEST_P(RleTest, RleV2_delta_increasing_sequance_unsigned) {
    runTest(RleVersion_2, 1024, 0, 1, false, false);
  }

  TEST_P(RleTest, RleV2_delta_increasing_sequance_unsigned_null) {
    runTest(RleVersion_2, 1024, 0, 1, false, false, 100);
  }

  TEST_P(RleTest, RleV2_delta_decreasing_sequance_unsigned) {
    runTest(RleVersion_2, 1024, 5000, -3, false, false);
  }

  TEST_P(RleTest, RleV2_delta_decreasing_sequance_signed) {
    runTest(RleVersion_2, 1024, 100, -3, false, true);
  }

  TEST_P(RleTest, RleV2_delta_decreasing_sequance_signed_null) {
    runTest(RleVersion_2, 1024, 100, -3, false, true, 500);
  }

  TEST_P(RleTest, RleV2_random_sequance_signed) {
    runTest(RleVersion_2, 1024, 0, 0, true, true);
  }

  TEST_P(RleTest, RleV2_all_null) {
    runTest(RleVersion_2, 1024, 100, -3, false, true, 1024);
  }

  TEST_P(RleTest, RleV2_delta_zero_unsigned) {
    runTest(RleVersion_2, 1024, 123, 0, false, false);
  }

  TEST_P(RleTest, RleV2_delta_zero_signed) {
    runTest(RleVersion_2, 1024, 123, 0, false, true);
  }

  TEST_P(RleTest, RleV2_short_repeat) {
    runTest(RleVersion_2, 8, 123, 0, false, false);
  }

  TEST_P(RleTest, RleV2_short_repeat_example) {
    int64_t data[5] = {10000, 10000, 10000, 10000, 10000};
    unsigned char expectedEncoded[3] = {0x0a, 0x27, 0x10};
    runExampleTest(data, 5, expectedEncoded, 3);
  }

  TEST_P(RleTest, RleV2_direct_example) {
    int64_t data[4] = {23713, 43806, 57005, 48879};
    unsigned char expectedEncoded[10] = {0x5e, 0x03, 0x5c, 0xa1, 0xab, 0x1e, 0xde, 0xad, 0xbe, 0xef};
    runExampleTest(data, 4, expectedEncoded, 10);
  }

  TEST_P(RleTest, RleV2_Patched_base_example) {
    int64_t data[20] = {2030, 2000, 2020, 1000000, 2040, 2050, 2060, 2070, 2080,
                        2090, 2100, 2110, 2120, 2130, 2140, 2150, 2160, 2170, 2180, 2190};
    unsigned char expectedEncoded[28] = {0x8e, 0x13, 0x2b, 0x21, 0x07, 0xd0, 0x1e, 0x00, 0x14,
                                0x70, 0x28, 0x32, 0x3c, 0x46, 0x50, 0x5a, 0x64, 0x6e, 0x78, 0x82, 0x8c,
                                0x96, 0xa0, 0xaa, 0xb4, 0xbe, 0xfc, 0xe8};
    runExampleTest(data, 20, expectedEncoded, 28);
  }

  TEST_P(RleTest, RleV2_Patched_base_big_gap) {
    // The input data contains 512 values: data[0...510] are of a repeated pattern of (2, 1), and
    // the last value (i.e. data[511]) is equal to 1024. This makes the last value to be the
    // only patched value and the gap of this patch is 511.
    const int numValues = 512;
    int64_t data[512];
    for (int i = 0; i < 511; i+=2) {
      data[i] = 2;
      data[i+1] = 1;
    }
    data[511] = 1024;

    // Invoke the encoder.
    const bool isSigned = true;
    MemoryOutputStream memStream(DEFAULT_MEM_STREAM_SIZE);

    std::unique_ptr<RleEncoder> encoder = getEncoder(RleVersion_2, memStream, isSigned);
    encoder->add(data, numValues, nullptr);
    encoder->flush();

    // Decode and verify.
    decodeAndVerify(RleVersion_2, memStream, data, numValues, nullptr, isSigned);
  }

  TEST_P(RleTest, RleV2_delta_example) {
    int64_t data[10] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
    unsigned char expectedEncoded[8] = {0xc6, 0x09, 0x02, 0x02, 0x22, 0x42, 0x42, 0x46};
    unsigned char unalignedExpectedEncoded[7] = {0xc4, 0x09, 0x02, 0x02, 0x4A, 0x28, 0xA6};
    if (alignBitpacking)
    {
      runExampleTest(data, 10, expectedEncoded, 8);
    }
    else
    {
      runExampleTest(data, 10, unalignedExpectedEncoded, 7);
    }
  }

  TEST_P(RleTest, RleV2_delta_example2) {
    int64_t data[7] = {0, 10000, 10001, 10001, 10002, 10003, 10003};
    unsigned char expectedEncoded[8] = {0xc2, 0x06, 0x0, 0xa0, 0x9c, 0x01, 0x45, 0x0};
    runExampleTest(data, 7, expectedEncoded, 8);
  }

  TEST_P(RleTest, RleV2_direct_repeat_example2) {
    int64_t data[9] = {23713, 43806, 57005, 48879, 10000, 10000, 10000, 10000, 10000};
    unsigned char expectedEncoded[13] = {0x5e, 0x03, 0x5c, 0xa1, 0xab, 0x1e, 0xde, 0xad, 0xbe, 0xef, 0x0a, 0x27, 0x10};
    runExampleTest(data, 9, expectedEncoded, 13);
  }

  INSTANTIATE_TEST_CASE_P(OrcTest, RleTest, Values(true, false));
}
<|endoftext|>


<commit_before>#include "in_memory_tracer.h"
#include <lightstep/tracer.h>

#define CATCH_CONFIG_MAIN
#include <lightstep/catch/catch.hpp>
#include <google/protobuf/util/message_differencer.h>
using namespace lightstep;
using namespace opentracing;

namespace lightstep {
std::shared_ptr<Tracer> make_lightstep_tracer(
    std::unique_ptr<Recorder>&& recorder);

collector::KeyValue to_key_value(StringRef key, const Value& value);
}  // namespace lightstep

//------------------------------------------------------------------------------
// has_tag
//------------------------------------------------------------------------------
static bool has_tag(const collector::Span& span, StringRef key,
                    const Value& value) {
  auto key_value = to_key_value(key, value);
  return std::find_if(
             std::begin(span.tags()), std::end(span.tags()),
             [&](const collector::KeyValue& other) {
               return google::protobuf::util::MessageDifferencer::Equals(
                   key_value, other);
             }) != std::end(span.tags());
}

//------------------------------------------------------------------------------
// has_relationship
//------------------------------------------------------------------------------
static bool has_relationship(SpanReferenceType relationship,
                             const collector::Span& span_a,
                             const collector::Span& span_b) {
  collector::Reference reference;
  switch (relationship) {
    case SpanReferenceType::ChildOfRef:
      reference.set_relationship(collector::Reference::CHILD_OF);
      break;
    case SpanReferenceType::FollowsFromRef:
      reference.set_relationship(collector::Reference::FOLLOWS_FROM);
      break;
  }
  *reference.mutable_span_context() = span_b.span_context();
  return std::find_if(
             std::begin(span_a.references()), std::end(span_a.references()),
             [&](const collector::Reference& other) {
               return google::protobuf::util::MessageDifferencer::Equals(
                   reference, other);
             }) != std::end(span_a.references());
}

//------------------------------------------------------------------------------
// tests
//------------------------------------------------------------------------------
TEST_CASE("in_memory_tracer") {
  auto recorder = new InMemoryRecorder();
  auto tracer = make_lightstep_tracer(std::unique_ptr<Recorder>(recorder));

  SECTION("StartSpan applies the provided tags.") {
    {
      auto span =
          tracer->StartSpan("a", {SetTag("abc", 123), SetTag("xyz", true)});
      CHECK(span);
      span->Finish();
    }
    auto span = recorder->top();
    CHECK(span.operation_name() == "a");
    CHECK(has_tag(span, "abc", 123));
    CHECK(has_tag(span, "xyz", true));
  }

  SECTION("calling Finish a second time does nothing.") {
    auto span = tracer->StartSpan("a");
    CHECK(span);
    span->Finish();
    CHECK(recorder->size() == 1);
    span->Finish();
    CHECK(recorder->size() == 1);
  }

  SECTION("the operation name can be set after the span is started.") {
    auto span = tracer->StartSpan("a");
    CHECK(span);
    span->SetOperationName("b");
    span->Finish();
    CHECK(recorder->top().operation_name() == "b");
  }
}
<commit_msg>Added test coverage for span references.<commit_after>#include "in_memory_tracer.h"
#include <lightstep/tracer.h>

#define CATCH_CONFIG_MAIN
#include <lightstep/catch/catch.hpp>
#include <google/protobuf/util/message_differencer.h>
using namespace lightstep;
using namespace opentracing;

namespace lightstep {
std::shared_ptr<Tracer> make_lightstep_tracer(
    std::unique_ptr<Recorder>&& recorder);

collector::KeyValue to_key_value(StringRef key, const Value& value);
}  // namespace lightstep

//------------------------------------------------------------------------------
// has_tag
//------------------------------------------------------------------------------
static bool has_tag(const collector::Span& span, StringRef key,
                    const Value& value) {
  auto key_value = to_key_value(key, value);
  return std::find_if(
             std::begin(span.tags()), std::end(span.tags()),
             [&](const collector::KeyValue& other) {
               return google::protobuf::util::MessageDifferencer::Equals(
                   key_value, other);
             }) != std::end(span.tags());
}

//------------------------------------------------------------------------------
// has_relationship
//------------------------------------------------------------------------------
static bool has_relationship(SpanReferenceType relationship,
                             const collector::Span& span_a,
                             const collector::Span& span_b) {
  collector::Reference reference;
  switch (relationship) {
    case SpanReferenceType::ChildOfRef:
      reference.set_relationship(collector::Reference::CHILD_OF);
      break;
    case SpanReferenceType::FollowsFromRef:
      reference.set_relationship(collector::Reference::FOLLOWS_FROM);
      break;
  }
  *reference.mutable_span_context() = span_b.span_context();
  return std::find_if(
             std::begin(span_a.references()), std::end(span_a.references()),
             [&](const collector::Reference& other) {
               return google::protobuf::util::MessageDifferencer::Equals(
                   reference, other);
             }) != std::end(span_a.references());
}

//------------------------------------------------------------------------------
// tests
//------------------------------------------------------------------------------
TEST_CASE("in_memory_tracer") {
  auto recorder = new InMemoryRecorder();
  auto tracer = make_lightstep_tracer(std::unique_ptr<Recorder>(recorder));

  SECTION("StartSpan applies the provided tags.") {
    {
      auto span =
          tracer->StartSpan("a", {SetTag("abc", 123), SetTag("xyz", true)});
      CHECK(span);
      span->Finish();
    }
    auto span = recorder->top();
    CHECK(span.operation_name() == "a");
    CHECK(has_tag(span, "abc", 123));
    CHECK(has_tag(span, "xyz", true));
  }

  SECTION("You can set a single child-of reference when starting a span") {
    auto span_a = tracer->StartSpan("a");
    CHECK(span_a);
    span_a->Finish();
    auto span_b = tracer->StartSpan("b", {ChildOf(&span_a->context())});
    CHECK(span_b);
    span_b->Finish();
    auto spans = recorder->spans();
    CHECK(spans.at(0).span_context().trace_id() ==
          spans.at(1).span_context().trace_id());
    CHECK(has_relationship(SpanReferenceType::ChildOfRef, spans.at(1),
                           spans.at(0)));
  }

  SECTION("You can set a single follows-from reference when starting a span") {
    auto span_a = tracer->StartSpan("a");
    CHECK(span_a);
    span_a->Finish();
    auto span_b = tracer->StartSpan("b", {FollowsFrom(&span_a->context())});
    CHECK(span_b);
    span_b->Finish();
    auto spans = recorder->spans();
    CHECK(spans.at(0).span_context().trace_id() ==
          spans.at(1).span_context().trace_id());
    CHECK(has_relationship(SpanReferenceType::FollowsFromRef, spans.at(1),
                           spans.at(0)));
  }

  SECTION("Multiple references are supported when starting a span") {
    auto span_a = tracer->StartSpan("a");
    CHECK(span_a);
    auto span_b = tracer->StartSpan("b");
    CHECK(span_b);
    auto span_c = tracer->StartSpan(
        "c", {ChildOf(&span_a->context()), FollowsFrom(&span_b->context())});
    span_a->Finish();
    span_b->Finish();
    span_c->Finish();
    auto spans = recorder->spans();
    CHECK(has_relationship(SpanReferenceType::ChildOfRef, spans.at(2),
                           spans.at(0)));
    CHECK(has_relationship(SpanReferenceType::FollowsFromRef, spans.at(2),
                           spans.at(1)));
  }

  SECTION("Calling Finish a second time does nothing.") {
    auto span = tracer->StartSpan("a");
    CHECK(span);
    span->Finish();
    CHECK(recorder->size() == 1);
    span->Finish();
    CHECK(recorder->size() == 1);
  }

  SECTION("The operation name can be changed after the span is started.") {
    auto span = tracer->StartSpan("a");
    CHECK(span);
    span->SetOperationName("b");
    span->Finish();
    CHECK(recorder->top().operation_name() == "b");
  }

  SECTION("Tags can be specified.") {
    auto span = tracer->StartSpan("a");
    CHECK(span);
    span->SetTag("abc", 123);
    span->Finish();
    CHECK(has_tag(recorder->top(), "abc", 123));
  }
}
<|endoftext|>


<commit_before>#ifndef __RANK_FILTER__
#define __RANK_FILTER__

#include <list>
#include <set>
#include <cmath>
#include <cassert>
#include <iostream>
#include <iterator>
#include <type_traits>
#include <utility>

#include <vigra/multi_array.hxx>
#include <vigra/linear_algebra.hxx>

namespace vigra
{

template<unsigned int N,
        class T1, class S1,
        class T2, class S2>
inline void lineRankOrderFilterND(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned int half_length, float rank, unsigned int axis = N - 1,
        typename std::enable_if<(N == 1)>::type *enabled = 0)
{
    // Will ignore boundaries initially.
    // Then will try adding reflection.

    // Rank must be in the range 0 to 1
    assert((0 <= rank) && (rank <= 1));

    const int rank_pos = round(rank * (2 * half_length));

    // The position of the
    typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 window_begin(0);
    std::multiset<T1> sorted_window;
    std::list< typename std::multiset<T1>::iterator > window_iters;

    // Get the initial sorted window.
    // Include the reflection.
    for (typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 j(half_length); j > 0; j--)
    {
        window_iters.push_back(sorted_window.insert(src[window_begin + j]));
    }
    for (typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 j(0); j <= half_length; j++)
    {
        window_iters.push_back(sorted_window.insert(src[window_begin + j]));
    }

    typename std::multiset<T1>::iterator rank_point = sorted_window.begin();

    for (int i = 0; i < rank_pos; i++)
    {
        rank_point++;
    }

    while ( window_begin < src.size() )
    {
        dest[window_begin] = *rank_point;

        typename std::multiset<T1>::iterator prev_iter(window_iters.front());
        T1 prev_value = *prev_iter;
        window_iters.pop_front();

        window_begin++;

        T1 next_value;
        if ( window_begin < (src.size() - half_length) )
        {
            next_value = src[window_begin + half_length];
        }
        else
        {
            next_value = src[2 * src.size() - (window_begin + half_length + 2)];
        }

        if ( ( *rank_point < *prev_iter ) && ( *rank_point <= next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));
        }
        else if ( ( *rank_point >= *prev_iter ) && ( *rank_point > next_value ) )
        {
            if ( rank_point == prev_iter )
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point--;

                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));
            }
        }
        else if ( ( *rank_point < *prev_iter ) && ( *rank_point > next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));

            rank_point--;
        }
        else if ( ( *rank_point >= *prev_iter ) && ( *rank_point <= next_value ) )
        {
            if (rank_point == prev_iter)
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point++;

                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));

                rank_point++;
            }
        }
    }
}

template<unsigned int N,
        class T1, class S1,
        class T2, class S2>
inline void lineRankOrderFilterND(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned int half_length, float rank, unsigned int axis = N - 1,
        typename std::enable_if<(N > 1)>::type *enabled = 0)
{
    typename vigra::MultiArrayView<N, T1, S1>::difference_type transposed_axes;

    for (unsigned int i = 0; i < N; i++)
    {
        transposed_axes[i] = i;
    }

    std::swap(transposed_axes[N - 1], transposed_axes[axis]);

    vigra::MultiArray<N, T1> src_transposed(src.transpose(transposed_axes));

    vigra::MultiArrayView<N, T1, S1> dest_transposed_view(dest.transpose(transposed_axes));

    typename vigra::MultiArrayView<N - 1, T1, S1>::difference_type pos;
    pos = 0;

    bool done = false;

    while (!done)
    {
        lineRankOrderFilter(src_transposed.bindInner(pos), dest_transposed_view.bindInner(pos), half_length, rank);

        bool carry = true;
        for (unsigned int i = 0; ( carry && (i < N) ); i++)
        {
            if ( (++pos[N - (i + 1)]) < src.shape()[N - (i + 1)])
            {
                carry = false;
            }
            else
            {
                pos[N - (i + 1)] = 0;
                carry = true;
            }
        }

        done = !carry;
    }
}

template<unsigned int N,
        class T1, class S1,
        class T2, class S2>
inline void lineRankOrderFilter(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned int half_length, float rank, unsigned int axis = N - 1)
{
    lineRankOrderFilterND(src, dest, half_length, rank, axis);
}

}

#endif //__RANK_FILTER__
<commit_msg>rank_filter.hxx: Changed enable_if arguments back to template arguments.<commit_after>#ifndef __RANK_FILTER__
#define __RANK_FILTER__

#include <list>
#include <set>
#include <cmath>
#include <cassert>
#include <iostream>
#include <iterator>
#include <type_traits>
#include <utility>

#include <vigra/multi_array.hxx>
#include <vigra/linear_algebra.hxx>

namespace vigra
{

template<unsigned int N,
        class T1, class S1,
        class T2, class S2,
        typename std::enable_if<(N == 1), int>::type = 0>
inline void lineRankOrderFilterND(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned int half_length, float rank, unsigned int axis = N - 1)
{
    // Will ignore boundaries initially.
    // Then will try adding reflection.

    // Rank must be in the range 0 to 1
    assert((0 <= rank) && (rank <= 1));

    const int rank_pos = round(rank * (2 * half_length));

    // The position of the
    typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 window_begin(0);
    std::multiset<T1> sorted_window;
    std::list< typename std::multiset<T1>::iterator > window_iters;

    // Get the initial sorted window.
    // Include the reflection.
    for (typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 j(half_length); j > 0; j--)
    {
        window_iters.push_back(sorted_window.insert(src[window_begin + j]));
    }
    for (typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 j(0); j <= half_length; j++)
    {
        window_iters.push_back(sorted_window.insert(src[window_begin + j]));
    }

    typename std::multiset<T1>::iterator rank_point = sorted_window.begin();

    for (int i = 0; i < rank_pos; i++)
    {
        rank_point++;
    }

    while ( window_begin < src.size() )
    {
        dest[window_begin] = *rank_point;

        typename std::multiset<T1>::iterator prev_iter(window_iters.front());
        T1 prev_value = *prev_iter;
        window_iters.pop_front();

        window_begin++;

        T1 next_value;
        if ( window_begin < (src.size() - half_length) )
        {
            next_value = src[window_begin + half_length];
        }
        else
        {
            next_value = src[2 * src.size() - (window_begin + half_length + 2)];
        }

        if ( ( *rank_point < *prev_iter ) && ( *rank_point <= next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));
        }
        else if ( ( *rank_point >= *prev_iter ) && ( *rank_point > next_value ) )
        {
            if ( rank_point == prev_iter )
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point--;

                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));
            }
        }
        else if ( ( *rank_point < *prev_iter ) && ( *rank_point > next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));

            rank_point--;
        }
        else if ( ( *rank_point >= *prev_iter ) && ( *rank_point <= next_value ) )
        {
            if (rank_point == prev_iter)
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point++;

                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));

                rank_point++;
            }
        }
    }
}

template<unsigned int N,
        class T1, class S1,
        class T2, class S2,
        typename std::enable_if<(N > 1), int>::type = 0>
inline void lineRankOrderFilterND(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned int half_length, float rank, unsigned int axis = N - 1)
{
    typename vigra::MultiArrayView<N, T1, S1>::difference_type transposed_axes;

    for (unsigned int i = 0; i < N; i++)
    {
        transposed_axes[i] = i;
    }

    std::swap(transposed_axes[N - 1], transposed_axes[axis]);

    vigra::MultiArray<N, T1> src_transposed(src.transpose(transposed_axes));

    vigra::MultiArrayView<N, T1, S1> dest_transposed_view(dest.transpose(transposed_axes));

    typename vigra::MultiArrayView<N - 1, T1, S1>::difference_type pos;
    pos = 0;

    bool done = false;

    while (!done)
    {
        lineRankOrderFilter(src_transposed.bindInner(pos), dest_transposed_view.bindInner(pos), half_length, rank);

        bool carry = true;
        for (unsigned int i = 0; ( carry && (i < N) ); i++)
        {
            if ( (++pos[N - (i + 1)]) < src.shape()[N - (i + 1)])
            {
                carry = false;
            }
            else
            {
                pos[N - (i + 1)] = 0;
                carry = true;
            }
        }

        done = !carry;
    }
}

template<unsigned int N,
        class T1, class S1,
        class T2, class S2>
inline void lineRankOrderFilter(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned int half_length, float rank, unsigned int axis = N - 1)
{
    lineRankOrderFilterND(src, dest, half_length, rank, axis);
}

}

#endif //__RANK_FILTER__
<|endoftext|>


<commit_before>/*
test_text

Do some simple text drawing

*/
#include "drawproc.h"
#include "guistyle.h"
#include <stdio.h>

static GUIStyle styler;
static const int gMaxMode = 3;
static int gMode = 0;

pb_rgba fb;
pb_rect keyRect = { 0, 0, 34, 34 };

/*
VK_SPACE, 168, 242, 204, 34
*/
//void draw();

void  mousePressed()
{
	gMode++;
	if (gMode >= gMaxMode) {
		gMode = 0;
	}

}

void  mouseMoved()
{
	keyRect.x = mouseX - keyRect.width / 2;
	keyRect.y = mouseY - keyRect.height / 2;
}

LRESULT CALLBACK keyReleased(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (wParam)
	{
	case VK_SPACE:
		write_PPM_binary("test_keyboard.ppm", gpb);
		break;

	case VK_RIGHT: // increase width of keyRect
		keyRect.width += 1;
		break;

	case VK_LEFT:
		keyRect.width -= 1;
		if (keyRect.width < 4) keyRect.width = 4;
		break;
	case VK_UP:
		keyRect.height += 1;
		break;
	case VK_DOWN:
		keyRect.height -= 1;
		if (keyRect.height < 4) keyRect.height = 4;
		break;
	}

	keyRect.x = mouseX - keyRect.width / 2;
	keyRect.y = mouseY - keyRect.height / 2;

	return 0;
}

// Draw information about the mouse
// location, buttons pressed, etc
void drawMouseInfo()
{
	// draw a white banner across the top
	noStroke();
	fill(pWhite);
	rect(0, fb.frame.height + 2, width, 24);

	// draw the key rectangle
	fill(RGBA(255, 238, 200, 180));
	stroke(pDarkGray);
	rect(keyRect.x, keyRect.y, keyRect.width, keyRect.height);

	// select verdana font
	setFont(verdana17);
	char infobuff[256];
	sprintf_s(infobuff, "Mouse X: %3d Y: %3d    Key: (%3d, %3d)(%3d, %3d)", mouseX, mouseY, keyRect.x,
		keyRect.y, keyRect.width, keyRect.height);
	fill(pBlack);
	textAlign(TX_LEFT, TX_TOP);
	text(infobuff, 0, fb.frame.height + 2);

}

void draw()
{
	background(pLightGray);
	backgroundImage(&fb);

	drawMouseInfo();
}

void setup()
{
	int ret = PPM_read_binary("c:/repos/graphicc/Test/windows-keyboard-60-keys.ppm", &fb);

	size(fb.frame.width+4, fb.frame.height+4+30);
	background(pLightGray);
	//noLoop();

	//setOnMousePressedHandler(mousePressed);
	//setOnMouseMovedHandler(mouseMoved);
	//setOnKeyReleasedHandler(keyReleased);
}

<commit_msg>Changed string format of tracking rectangle information, using float<commit_after>/*
test_text

Do some simple text drawing

*/
#include "drawproc.h"
#include "guistyle.h"
#include <stdio.h>

static GUIStyle styler;
static const int gMaxMode = 3;
static int gMode = 0;

pb_rgba fb;
pb_rect keyRect = { 0, 0, 34, 34 };

/*
VK_SPACE, 168, 242, 204, 34
*/
//void draw();

void  mousePressed()
{
	gMode++;
	if (gMode >= gMaxMode) {
		gMode = 0;
	}

}

void  mouseMoved()
{
	keyRect.x = mouseX - keyRect.width / 2;
	keyRect.y = mouseY - keyRect.height / 2;
}

LRESULT CALLBACK keyReleased(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (wParam)
	{
	case VK_SPACE:
		write_PPM_binary("test_keyboard.ppm", gpb);
		break;

	case VK_RIGHT: // increase width of keyRect
		keyRect.width += 1;
		break;

	case VK_LEFT:
		keyRect.width -= 1;
		if (keyRect.width < 4) keyRect.width = 4;
		break;
	case VK_UP:
		keyRect.height += 1;
		break;
	case VK_DOWN:
		keyRect.height -= 1;
		if (keyRect.height < 4) keyRect.height = 4;
		break;
	}

	keyRect.x = mouseX - keyRect.width / 2;
	keyRect.y = mouseY - keyRect.height / 2;

	return 0;
}

// Draw information about the mouse
// location, buttons pressed, etc
void drawMouseInfo()
{
	// draw a white banner across the top
	noStroke();
	fill(pWhite);
	rect(0, fb.frame.height + 2, width, 24);

	// draw the key rectangle
	fill(RGBA(255, 238, 200, 180));
	stroke(pDarkGray);
	rect(keyRect.x, keyRect.y, keyRect.width, keyRect.height);

	// select verdana font
	setFont(verdana17);
	char infobuff[256];
	sprintf_s(infobuff, "Mouse X: %3d Y: %3d    Key: (%3f, %3f)(%3.0f, %3.0f)", mouseX, mouseY, keyRect.x,
		keyRect.y, keyRect.width, keyRect.height);
	fill(pBlack);
	textAlign(TX_LEFT, TX_TOP);
	text(infobuff, 0, fb.frame.height + 2);

}

void draw()
{
	background(pLightGray);
	backgroundImage(&fb);

	drawMouseInfo();
}

void setup()
{
	int ret = PPM_read_binary("c:/repos/graphicc/Test/windows-keyboard-60-keys.ppm", &fb);

	size(fb.frame.width+4, fb.frame.height+4+30);
	background(pLightGray);
	//noLoop();

	//setOnMousePressedHandler(mousePressed);
	//setOnMouseMovedHandler(mouseMoved);
	//setOnKeyReleasedHandler(keyReleased);
}

<|endoftext|>


<commit_before>#include "TestAlgorithm.h"

/**
 * @brief TestAlgorithm::TestAlgorithm create new algorithm with given ID
 * @param id algorithm ID
 */
TestAlgorithm::TestAlgorithm() {
    mId = "default";
    mName = "Test algorithm";
    mDescription = "dummy algorithm that scores randomly";
}

/**
 * @brief TestAlgorithm::run start the search
 * @return a list of data packets containing results
 */
QList<DataPacket*> TestAlgorithm::run() {
    QList<DataPacket*> list;
    SearchResult* result = new SearchResult();

    for (QString& datasetPath : mQuery->getDatasets()) {
        Dataset dataset(datasetPath);

        for (Medium* medium : dataset.getMediaList()) {
            SearchObject* object = new SearchObject();
            object->setMedium(medium->getPath());

            //new result element
            SearchResultElement* resultElement = new SearchResultElement();
            resultElement->setSearchObject(*object);
            resultElement->setScore(std::rand() % 20);

            //add to result list
            result->addResultElement(*resultElement);
        }
    }

    list.append((DataPacket*)result);
    return list;
}

/**
 * @brief TestAlgorithm::cancel terminate the algorithm
 */
void TestAlgorithm::cancel() {

}

/**
 * @brief TestAlgorithm::setInputs set input for algorithm
 * @param inputDataList input data
 * @return true if input data is accepted
 */
bool TestAlgorithm::setInputs(const QList<DataPacket*>& inputDataList) {
    if (inputDataList.length() < 1) {  //illegal number of parameters
        return false;
    }

    DataPacket* packet = inputDataList.value(0);
    if (packet->getType() != DataPacket::Type::SEARCHQUERY) {   //invalid query
        return false;
    }

    mQuery = dynamic_cast<SearchQuery*>(packet);
    return true;
}

/**
 * @brief TestAlgorithm::setParameters set algorithm parameters
 * @param parameters the parameters
 * @return true if the algorithm accepts the parameters
 */
bool TestAlgorithm::setParameters(const QJsonObject& parameters) {
    Q_UNUSED(parameters);
    return true;
}

/**
 * @brief TestAlgorithm::supportsProgressInfo
 * @return true if progress information will be sent to application when the search runs
 */
bool TestAlgorithm::supportsProgressInfo() {
    return false;
}
<commit_msg>add some optimization for TestAlgorithm<commit_after>#include "TestAlgorithm.h"

/**
 * @brief TestAlgorithm::TestAlgorithm create new algorithm with given ID
 * @param id algorithm ID
 */
TestAlgorithm::TestAlgorithm() {
    mId = "default";
    mName = "Test algorithm";
    mDescription = "dummy algorithm that scores randomly";
}

/**
 * @brief TestAlgorithm::run start the search
 * @return a list of data packets containing results
 */
QList<DataPacket*> TestAlgorithm::run() {
    QList<DataPacket*> list;
    SearchResult* result = new SearchResult();

    for (QString& datasetPath : mQuery->getDatasets()) {
        Dataset dataset(datasetPath);

        for (Medium* medium : dataset.getMediaList()) {
            SearchObject* object = new SearchObject();
            object->setMedium(medium->getPath());
            object->setSourceDataset(dataset.getPath());

            //new result element
            SearchResultElement* resultElement = new SearchResultElement();
            resultElement->setSearchObject(*object);
            resultElement->setScore(std::rand() % 20);

            //add to result list
            result->addResultElement(*resultElement);
        }
    }

    list.append(dynamic_cast<DataPacket*>(result));
    return list;
}

/**
 * @brief TestAlgorithm::cancel terminate the algorithm
 */
void TestAlgorithm::cancel() {

}

/**
 * @brief TestAlgorithm::setInputs set input for algorithm
 * @param inputDataList input data
 * @return true if input data is accepted
 */
bool TestAlgorithm::setInputs(const QList<DataPacket*>& inputDataList) {
    if (inputDataList.length() != 1) {  //illegal number of parameters
        return false;
    }

    DataPacket* packet = inputDataList.value(0);
    if (packet->getType() != DataPacket::Type::SEARCHQUERY) {   //invalid query
        return false;
    }

    mQuery = dynamic_cast<SearchQuery*>(packet);
    return true;
}

/**
 * @brief TestAlgorithm::setParameters set algorithm parameters
 * @param parameters the parameters
 * @return true if the algorithm accepts the parameters
 */
bool TestAlgorithm::setParameters(const QJsonObject& parameters) {
    Q_UNUSED(parameters);
    return true;
}

/**
 * @brief TestAlgorithm::supportsProgressInfo
 * @return true if progress information will be sent to application when the search runs
 */
bool TestAlgorithm::supportsProgressInfo() {
    return false;
}
<|endoftext|>


<commit_before>#include "gvki/Logger.h"
#include "gvki/PathSeperator.h"
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <errno.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include "string.h"
#include "gvki/Debug.h"

// For mkdir(). FIXME: Make windows compatible
#include <sys/stat.h>
// For opendir(). FIXME: Make windows compatible
#include <dirent.h>

// For getcwd()
#include <unistd.h>

using namespace std;
using namespace gvki;

// Maximum number of files or directories
// that can be created
static const int maxFiles = 10000;

Logger& Logger::Singleton()
{
    static Logger l;
    return l;
}

Logger::Logger()
{
    int count = 0;
    bool success= false;

    // FIXME: Reading from the environment probably doesn't belong in here
    // but it makes implementing the singleton a lot easier
    std::string directoryPrefix;

    const char* envTemp = getenv("GVKI_ROOT");
    if (envTemp)
    {
        DEBUG_MSG("Using GVKI_ROOT value as destination for directories");
        DIR* dh = opendir(envTemp);
        if (dh == NULL)
        {
            ERROR_MSG(strerror(errno) << ". Directory was :" << envTemp);
            exit(1);
        }
        else
            closedir(dh);

        directoryPrefix = envTemp;

    }
    else
    {
        // Use the current working directory
        DEBUG_MSG("Using current working directory as destination for directories");

        // FIXME: Hard-coding this size is gross
        char cwdArray[1024];
        char* cwdResult = getcwd(cwdArray, sizeof(cwdArray)/sizeof(char));
        if (!cwdResult)
        {
            ERROR_MSG(strerror(errno) << ". Could not read the current working directory");
            exit(1);
        }
        else
            directoryPrefix = cwdResult;

    }
    directoryPrefix += PATH_SEP "gvki";
    DEBUG_MSG("Directory prefix is \"" << directoryPrefix << "\"");

    // Keep trying a directoryPrefix name with a number as suffix
    // until we find an available one or we exhaust the maximum
    // allowed number
    while (count < maxFiles)
    {
        stringstream ss;
        ss <<  directoryPrefix << "-" << count;
        ++count;

        // Make the directoryPrefix
        if (mkdir(ss.str().c_str(), 0770) != 0)
        {
            if (errno != EEXIST)
            {
                ERROR_MSG(strerror(errno) << ". Directory was :" << directoryPrefix);
                exit(1);
            }

            // It already exists, try again
            continue;
        }

        this->directory = ss.str();
        success = true;
        break;
    }

    if (!success)
    {
        ERROR_MSG("Exhausted available directory names or couldn't create any");
        exit(1);
    }

    DEBUG_MSG("Directory used for logging is \"" << this->directory << "\"");

    openLog();
}

void Logger::openLog()
{
    // FIXME: We should use mkstemp() or something
    std::stringstream ss;
    ss << directory << PATH_SEP << "log.json";
    output = new std::ofstream(ss.str().c_str(), std::ofstream::out | std::ofstream::ate);

    if (! output->good())
    {
        ERROR_MSG("Failed to create file (" << ss.str() <<  ") to write log to");
        exit(1);
    }

    // Start of JSON array
    *output << "[" << std::endl;
}

void Logger::closeLog()
{
    // End of JSON array
    *output << std::endl << "]" << std::endl;
    output->close();
}

Logger::~Logger()
{
    closeLog();
    delete output;
}

void Logger::dump(cl_kernel k)
{
    // Output JSON format defined by
    // http://multicore.doc.ic.ac.uk/tools/GPUVerify/docs/json_format.html
    KernelInfo& ki = kernels[k];

    static bool isFirst = true;

    if (!isFirst)
    {
        // Emit array element seperator
        // to seperate from previous dump
        *output << "," << endl;
    }
    isFirst = false;

    *output << "{" << endl << "\"language\": \"OpenCL\"," << endl;

    std::string kernelSourceFile = dumpKernelSource(ki);

    *output << "\"kernel_file\": \"" << kernelSourceFile << "\"," << endl;

    // FIXME: Teach GPUVerify how to handle non zero global_offset
    // FIXME: Document this json attribute!
    // Only emit global_offset if its non zero
    bool hasNonZeroGlobalOffset = false;
    for (int index=0; index < ki.globalWorkOffset.size() ; ++index)
    {
        if (ki.globalWorkOffset[index] != 0)
            hasNonZeroGlobalOffset = true;
    }
    if (hasNonZeroGlobalOffset)
    {
        *output << "\"global_offset\": ";
        printJSONArray(ki.globalWorkOffset);
        *output << "," << endl;
    }

    *output << "\"global_size\": ";
    printJSONArray(ki.globalWorkSize);
    *output << "," << endl;

    *output << "\"local_size\": ";
    printJSONArray(ki.localWorkSize);
    *output << "," << endl;

    assert( (ki.globalWorkOffset.size() == ki.globalWorkSize.size()) &&
            (ki.globalWorkSize.size() == ki.localWorkSize.size()) &&
            "dimension mismatch");

    *output << "\"entry_point\": \"" << ki.entryPointName << "\"";

    // entry_point might be the last entry is there were no kernel args
    if (ki.arguments.size() == 0)
        *output << endl;
    else
    {
        *output << "," << endl << "\"kernel_arguments\": [ " << endl;
        for (int argIndex=0; argIndex < ki.arguments.size() ; ++argIndex)
        {
            printJSONKernelArgumentInfo(ki.arguments[argIndex]);
            if (argIndex != (ki.arguments.size() -1))
                *output << "," << endl;
        }
        *output << endl << "]" << endl;
    }

    *output << "}";
}

void Logger::printJSONArray(std::vector<size_t>& array)
{
    *output << "[ ";
    for (int index=0; index < array.size(); ++index)
    {
        *output << array[index];

        if (index != (array.size() -1))
            *output << ", ";
    }
    *output << "]";
}

void Logger::printJSONKernelArgumentInfo(ArgInfo& ai)
{
    *output << "{";
    if (ai.argValue == NULL)
    {
        // NULL was passed to clSetKernelArg()
        // That implies its for unallocated memory
        *output << "\"type\": \"array\",";

        // If the arg is for local memory
        if (ai.argSize != sizeof(cl_mem) && ai.argSize != sizeof(cl_sampler))
        {
            // We assume this means this arguments is for local memory
            // where size actually means the sizeof the underlying buffer
            // rather than the size of the type.
            *output << "\"size\" : " << ai.argSize;
        }
        *output << "}";
        return;
    }

    // FIXME:
    // Eurgh... the spec says
    // ```
    // If the argument is a buffer object, the arg_value pointer can be NULL or
    // point to a NULL value in which case a NULL value will be used as the
    // value for the argument declared as a pointer to __global or __constant
    // memory in the kernel.  ```
    //
    // This makes it impossible (seeing as we don't know which address space
    // the arguments are in) to work out the argument type once derefencing the
    // pointer and finding it's equal zero because it could be a scalar constant
    // (of value 0) or it could be an unintialised array!

    // Hack:
    // It's hard to determine what type the argument is.
    // We can't dereference the void* to check if
    // it points to cl_mem we previously stored
    //
    // In some implementations cl_mem will be a pointer
    // which poses a risk if a scalar parameter of the same size
    // as the pointer type.
    if (ai.argSize == sizeof(cl_mem))
    {
       cl_mem mightBecl_mem = *((cl_mem*) ai.argValue);

       // We might be reading invalid data now
       if (buffers.count(mightBecl_mem) == 1)
       {
           // We're going to assume it's cl_mem that we saw before
           *output << "\"type\": \"array\",";
           BufferInfo& bi = buffers[mightBecl_mem];

           *output << "\"size\": " << bi.size << "}";
           return;
       }

    }

    // Hack: a similar hack of the image types
    if (ai.argSize == sizeof(cl_mem))
    {
       cl_mem mightBecl_mem = *((cl_mem*) ai.argValue);

       // We might be reading invalid data now
       if (images.count(mightBecl_mem) == 1)
       {
           // We're going to assume it's cl_mem that we saw before
           *output << "\"type\": \"image\"}";
           return;
       }

    }

    // Hack: a similar hack for the samplers
    if (ai.argSize == sizeof(cl_sampler))
    {
       cl_sampler mightBecl_sampler = *((cl_sampler*) ai.argValue);

       // We might be reading invalid data now
       if (samplers.count(mightBecl_sampler) == 1)
       {
           // We're going to assume it's cl_mem that we saw before
           *output << "\"type\": \"sampler\"}";
           return;
       }

    }

    // I guess it's scalar???
    *output << "\"type\": \"scalar\",";
    *output << " \"value\": \"0x";
    // Print the value as hex
    uint8_t* asByte = (uint8_t*) ai.argValue;
    // We assume the host is little endian so to print the values
    // we need to go through the array bytes backwards
    for (int byteIndex= ai.argSize -1; byteIndex >=0 ; --byteIndex)
    {
       *output << std::hex << std::setfill('0') << std::setw(2) << ( (unsigned) asByte[byteIndex]);
    }
    *output << "\"" << std::dec; //std::hex is sticky so switch back to decimal

    *output << "}";
    return;

}

static bool file_exists(std::string& name) {
	ifstream f(name.c_str());
	bool result = f.good();
	f.close();
	return result;
}

// Define the strict weak ordering over ProgramInfo instances
// Is this correct?
bool ProgramInfoCacheCompare::operator() (const ProgramInfo& lhs, const ProgramInfo& rhs) const
{
    // Use the fact that a strict-weak order is already defined over std::vector<>
    return lhs.sources < rhs.sources;
}

std::string Logger::dumpKernelSource(KernelInfo& ki)
{
    ProgramInfo& pi = programs[ki.program];

    // See if we can used a file that we already printed.
    // This avoid writing duplicate files.
    ProgCacheMapTy::iterator it = WrittenKernelFileCache.find(pi);
    if ( it != WrittenKernelFileCache.end() )
    {
        return it->second;
    }

    int count = 0;
    bool success = false;
    // FIXME: I really want a std::unique_ptr
    std::ofstream* kos = 0;
    std::string theKernelPath;
    while (count < maxFiles)
    {
        stringstream ss;
        ss << ki.entryPointName << "." << count << ".cl";

        ++count;

        std::string withDir = (directory + PATH_SEP) + ss.str();
        if (!file_exists(withDir))
        {
           kos = new std::ofstream(withDir.c_str());

           if (!kos->good())
           {
                kos->close();
                delete kos;
                continue;
           }

           success = true;
           theKernelPath = ss.str();
           break;
        }
    }

    if (!success)
    {
        ERROR_MSG("Failed to log kernel output");
        return std::string("FIXME");
    }

    // Write kernel source

    for (vector<string>::const_iterator b = pi.sources.begin(), e = pi.sources.end(); b != e; ++b)
    {
        *kos << *b;
    }

    // Urgh this is bad, need RAII!
    kos->close();
    delete kos;

    // Store in cache
    assert(WrittenKernelFileCache.count(pi) == 0 && "ProgramInfo already in cache!");
    WrittenKernelFileCache[pi] = theKernelPath;

    return theKernelPath;
}
<commit_msg>Modifications to allow this to compile and run under Windows<commit_after>#include "gvki/Logger.h"
#include "gvki/PathSeperator.h"
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <errno.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include "string.h"
#include "gvki/Debug.h"

#include <sys/stat.h>

#ifndef _WIN32

#include <dirent.h>
#include <unistd.h>
#define MKDIR_FAILS(d)     (mkdir(d, 0770) != 0)
#define DIR_ALREADY_EXISTS (errno == EEXIST)

static void checkDirectoryExists(const char* dirName) {
    DIR* dh = opendir(dirName);
    if (dh != NULL)
    {
        closedir(dh);
        return;
    }
    ERROR_MSG(strerror(errno) << ". Directory was :" << dirName);
    exit(1);
}

#else

#include <inttypes.h>
#include <Windows.h>
#define MKDIR_FAILS(d)     (CreateDirectory(ss.str().c_str(), NULL) == 0)
#define DIR_ALREADY_EXISTS (GetLastError() == ERROR_ALREADY_EXISTS)

static void checkDirectoryExists(const char* dirName) {
    DWORD ftyp = GetFileAttributesA(dirName);
    if ((ftyp != INVALID_FILE_ATTRIBUTES) && ftyp & FILE_ATTRIBUTE_DIRECTORY)
        return;
    ERROR_MSG(strerror(errno) << ". Directory was :" << dirName);
    exit(1);
}

#endif

using namespace std;
using namespace gvki;

// Maximum number of files or directories
// that can be created
static const int maxFiles = 10000;

Logger& Logger::Singleton()
{
    static Logger l;
    return l;
}

Logger::Logger()
{
    int count = 0;
    bool success= false;

    // FIXME: Reading from the environment probably doesn't belong in here
    // but it makes implementing the singleton a lot easier
    std::string directoryPrefix;

    const char* envTemp = getenv("GVKI_ROOT");
    if (envTemp)
    {
        DEBUG_MSG("Using GVKI_ROOT value as destination for directories");

        checkDirectoryExists(envTemp);

        directoryPrefix = envTemp;

    }
    else
    {
        // Use the current working directory
        DEBUG_MSG("Using current working directory as destination for directories");

        // FIXME: Hard-coding this size is gross
        #define MAX_DIR_LENGTH 1024

#ifndef _WIN32
        char cwdArray[MAX_DIR_LENGTH];
        char* cwdResult = getcwd(cwdArray, sizeof(cwdArray)/sizeof(char));
        if (!cwdResult)
#else
        char cwdResult[MAX_DIR_LENGTH];
        if (GetCurrentDirectory(MAX_DIR_LENGTH, cwdResult) == 0)
#endif
        {
            ERROR_MSG(strerror(errno) << ". Could not read the current working directory");
            exit(1);
        }
        else
            directoryPrefix = cwdResult;
    }
    directoryPrefix += PATH_SEP "gvki";
    DEBUG_MSG("Directory prefix is \"" << directoryPrefix << "\"");

    // Keep trying a directoryPrefix name with a number as suffix
    // until we find an available one or we exhaust the maximum
    // allowed number
    while (count < maxFiles)
    {
        stringstream ss;
        ss <<  directoryPrefix << "-" << count;
        ++count;

        // Make the directoryPrefix
        if (MKDIR_FAILS(ss.str().c_str()))
        {
            if (!DIR_ALREADY_EXISTS)
            {
                ERROR_MSG(strerror(errno) << ". Directory was :" << directoryPrefix);
                exit(1);
            }

            // It already exists, try again
            continue;
        }

        this->directory = ss.str();
        success = true;
        break;
    }

    if (!success)
    {
        ERROR_MSG("Exhausted available directory names or couldn't create any");
        exit(1);
    }

    DEBUG_MSG("Directory used for logging is \"" << this->directory << "\"");

    openLog();
}

void Logger::openLog()
{
    // FIXME: We should use mkstemp() or something
    std::stringstream ss;
    ss << directory << PATH_SEP << "log.json";
    output = new std::ofstream(ss.str().c_str(), std::ofstream::out | std::ofstream::ate);

    if (! output->good())
    {
        ERROR_MSG("Failed to create file (" << ss.str() <<  ") to write log to");
        exit(1);
    }

    // Start of JSON array
    *output << "[" << std::endl;
}

void Logger::closeLog()
{
    // End of JSON array
    *output << std::endl << "]" << std::endl;
    output->close();
}

Logger::~Logger()
{
    closeLog();
    delete output;
}

void Logger::dump(cl_kernel k)
{
    // Output JSON format defined by
    // http://multicore.doc.ic.ac.uk/tools/GPUVerify/docs/json_format.html
    KernelInfo& ki = kernels[k];

    static bool isFirst = true;

    if (!isFirst)
    {
        // Emit array element seperator
        // to seperate from previous dump
        *output << "," << endl;
    }
    isFirst = false;

    *output << "{" << endl << "\"language\": \"OpenCL\"," << endl;

    std::string kernelSourceFile = dumpKernelSource(ki);

    *output << "\"kernel_file\": \"" << kernelSourceFile << "\"," << endl;

    // FIXME: Teach GPUVerify how to handle non zero global_offset
    // FIXME: Document this json attribute!
    // Only emit global_offset if its non zero
    bool hasNonZeroGlobalOffset = false;
    for (int index=0; index < ki.globalWorkOffset.size() ; ++index)
    {
        if (ki.globalWorkOffset[index] != 0)
            hasNonZeroGlobalOffset = true;
    }
    if (hasNonZeroGlobalOffset)
    {
        *output << "\"global_offset\": ";
        printJSONArray(ki.globalWorkOffset);
        *output << "," << endl;
    }

    *output << "\"global_size\": ";
    printJSONArray(ki.globalWorkSize);
    *output << "," << endl;

    *output << "\"local_size\": ";
    printJSONArray(ki.localWorkSize);
    *output << "," << endl;

    assert( (ki.globalWorkOffset.size() == ki.globalWorkSize.size()) &&
            (ki.globalWorkSize.size() == ki.localWorkSize.size()) &&
            "dimension mismatch");

    *output << "\"entry_point\": \"" << ki.entryPointName << "\"";

    // entry_point might be the last entry is there were no kernel args
    if (ki.arguments.size() == 0)
        *output << endl;
    else
    {
        *output << "," << endl << "\"kernel_arguments\": [ " << endl;
        for (int argIndex=0; argIndex < ki.arguments.size() ; ++argIndex)
        {
            printJSONKernelArgumentInfo(ki.arguments[argIndex]);
            if (argIndex != (ki.arguments.size() -1))
                *output << "," << endl;
        }
        *output << endl << "]" << endl;
    }

    *output << "}";
}

void Logger::printJSONArray(std::vector<size_t>& array)
{
    *output << "[ ";
    for (int index=0; index < array.size(); ++index)
    {
        *output << array[index];

        if (index != (array.size() -1))
            *output << ", ";
    }
    *output << "]";
}

void Logger::printJSONKernelArgumentInfo(ArgInfo& ai)
{
    *output << "{";
    if (ai.argValue == NULL)
    {
        // NULL was passed to clSetKernelArg()
        // That implies its for unallocated memory
        *output << "\"type\": \"array\",";

        // If the arg is for local memory
        if (ai.argSize != sizeof(cl_mem) && ai.argSize != sizeof(cl_sampler))
        {
            // We assume this means this arguments is for local memory
            // where size actually means the sizeof the underlying buffer
            // rather than the size of the type.
            *output << "\"size\" : " << ai.argSize;
        }
        *output << "}";
        return;
    }

    // FIXME:
    // Eurgh... the spec says
    // ```
    // If the argument is a buffer object, the arg_value pointer can be NULL or
    // point to a NULL value in which case a NULL value will be used as the
    // value for the argument declared as a pointer to __global or __constant
    // memory in the kernel.  ```
    //
    // This makes it impossible (seeing as we don't know which address space
    // the arguments are in) to work out the argument type once derefencing the
    // pointer and finding it's equal zero because it could be a scalar constant
    // (of value 0) or it could be an unintialised array!

    // Hack:
    // It's hard to determine what type the argument is.
    // We can't dereference the void* to check if
    // it points to cl_mem we previously stored
    //
    // In some implementations cl_mem will be a pointer
    // which poses a risk if a scalar parameter of the same size
    // as the pointer type.
    if (ai.argSize == sizeof(cl_mem))
    {
       cl_mem mightBecl_mem = *((cl_mem*) ai.argValue);

       // We might be reading invalid data now
       if (buffers.count(mightBecl_mem) == 1)
       {
           // We're going to assume it's cl_mem that we saw before
           *output << "\"type\": \"array\",";
           BufferInfo& bi = buffers[mightBecl_mem];

           *output << "\"size\": " << bi.size << "}";
           return;
       }

    }

    // Hack: a similar hack of the image types
    if (ai.argSize == sizeof(cl_mem))
    {
       cl_mem mightBecl_mem = *((cl_mem*) ai.argValue);

       // We might be reading invalid data now
       if (images.count(mightBecl_mem) == 1)
       {
           // We're going to assume it's cl_mem that we saw before
           *output << "\"type\": \"image\"}";
           return;
       }

    }

    // Hack: a similar hack for the samplers
    if (ai.argSize == sizeof(cl_sampler))
    {
       cl_sampler mightBecl_sampler = *((cl_sampler*) ai.argValue);

       // We might be reading invalid data now
       if (samplers.count(mightBecl_sampler) == 1)
       {
           // We're going to assume it's cl_mem that we saw before
           *output << "\"type\": \"sampler\"}";
           return;
       }

    }

    // I guess it's scalar???
    *output << "\"type\": \"scalar\",";
    *output << " \"value\": \"0x";
    // Print the value as hex
    uint8_t* asByte = (uint8_t*) ai.argValue;
    // We assume the host is little endian so to print the values
    // we need to go through the array bytes backwards
    for (int byteIndex= ai.argSize -1; byteIndex >=0 ; --byteIndex)
    {
       *output << std::hex << std::setfill('0') << std::setw(2) << ( (unsigned) asByte[byteIndex]);
    }
    *output << "\"" << std::dec; //std::hex is sticky so switch back to decimal

    *output << "}";
    return;

}

static bool file_exists(std::string& name) {
	ifstream f(name.c_str());
	bool result = f.good();
	f.close();
	return result;
}

// Define the strict weak ordering over ProgramInfo instances
// Is this correct?
bool ProgramInfoCacheCompare::operator() (const ProgramInfo& lhs, const ProgramInfo& rhs) const
{
    // Use the fact that a strict-weak order is already defined over std::vector<>
    return lhs.sources < rhs.sources;
}

std::string Logger::dumpKernelSource(KernelInfo& ki)
{
    ProgramInfo& pi = programs[ki.program];

    // See if we can used a file that we already printed.
    // This avoid writing duplicate files.
    ProgCacheMapTy::iterator it = WrittenKernelFileCache.find(pi);
    if ( it != WrittenKernelFileCache.end() )
    {
        return it->second;
    }

    int count = 0;
    bool success = false;
    // FIXME: I really want a std::unique_ptr
    std::ofstream* kos = 0;
    std::string theKernelPath;
    while (count < maxFiles)
    {
        stringstream ss;
        ss << ki.entryPointName << "." << count << ".cl";

        ++count;

        std::string withDir = (directory + PATH_SEP) + ss.str();
        if (!file_exists(withDir))
        {
           kos = new std::ofstream(withDir.c_str());

           if (!kos->good())
           {
                kos->close();
                delete kos;
                continue;
           }

           success = true;
           theKernelPath = ss.str();
           break;
        }
    }

    if (!success)
    {
        ERROR_MSG("Failed to log kernel output");
        return std::string("FIXME");
    }

    // Write kernel source

    for (vector<string>::const_iterator b = pi.sources.begin(), e = pi.sources.end(); b != e; ++b)
    {
        *kos << *b;
    }

    // Urgh this is bad, need RAII!
    kos->close();
    delete kos;

    // Store in cache
    assert(WrittenKernelFileCache.count(pi) == 0 && "ProgramInfo already in cache!");
    WrittenKernelFileCache[pi] = theKernelPath;

    return theKernelPath;
}
<|endoftext|>


<commit_before>#ifndef SIMPLE_HERO_CPP_
#define SIMPLE_HERO_CPP_

#include "simple_hero.hpp"
#include <stdlib.h>
#include <queue>

Simple_Hero::Simple_Hero( int type ) : Actor( type ) {
	actor_list = vector<Vertex>();
	made_graph = false;

}

const char* Simple_Hero::getActorId() {
	return "simplehero";
}

const char* Simple_Hero::getNetId() {
	return "hammesa";
}

void Simple_Hero::update_vertices( GraphMap* map ) {
	int x, y;
	actor_list.resize( map->getNumActors() );

	for( int i = 0; i < map->getNumActors(); i++ ) {
		map->getActorPosition( i, x, y );
		actor_list[i] = Vertex( x, y );
	}

	if( !made_graph ) make_graph( map );
}

void Simple_Hero::make_graph( GraphMap* map ) {
	graph_width  = map->getWidth();
	graph_height = map->getHeight();

	graph.reserve( graph_width );

	for(int i = 0; i < graph_width; i++ ) {
		graph[i].reserve( graph_height );
	}

	update_vertices( map );
	made_graph = true;
}

Vertex& Simple_Hero::get_vertex( int x, int y ) {
	if( !made_graph ) {
		printf("Called get_vertex without initializing graph\n");
		exit(0);
	}

	return graph[x][y];

}

int Simple_Hero::select_neighbor( GraphMap* map, int x, int y ) {

	return 0;
}

int Simple_Hero::where_go( GraphMap* map, int x1, int y1, int x2, int y2 ) {
	queue<Vertex> v_q;

	Vertex source ( x1, y1 );
	Vertex target ( x2, y2 );
	Vertex popped, temp;

	v_q.push( source );

	while( !v_q.empty() ) {
		popped = v_q.front();

		if( popped == target ) break;

		if( popped.visited ) {
			v_q.pop();
			continue;
		}

		for( int i = 0; i < map->getNumNeighbors( popped.x, popped.y ); i++ ) {
			int a, b;
			map->getNeighbor( popped.x, popped.y, i, a, b );
			temp = get_vertex( a, b );
			temp.prev = &popped;
			temp.visited = true;
			v_q.push( temp );
		}

	}

	return 0;
}

Simple_Hero::~Simple_Hero() {}

#endif
<commit_msg>Finished Djikstra's Algorithm, added input checking<commit_after>#ifndef SIMPLE_HERO_CPP_
#define SIMPLE_HERO_CPP_

#include "simple_hero.hpp"
#include <stdlib.h>
#include <queue>

Simple_Hero::Simple_Hero( int type ) : Actor( type ) {
	actor_list = vector<Vertex>();
	made_graph = false;

}

const char* Simple_Hero::getActorId() {
	return "simplehero";
}

const char* Simple_Hero::getNetId() {
	return "hammesa";
}

void Simple_Hero::update_vertices( GraphMap* map ) {
	int x, y;
	actor_list.resize( map->getNumActors() );

	for( int i = 0; i < map->getNumActors(); i++ ) {
		map->getActorPosition( i, x, y );
		actor_list[i] = Vertex( x, y );
	}

	if( !made_graph ) make_graph( map );
}

void Simple_Hero::make_graph( GraphMap* map ) {
	graph_width  = map->getWidth();
	graph_height = map->getHeight();

	graph.reserve( graph_width );

	for(int i = 0; i < graph_width; i++ ) {
		graph[i].reserve( graph_height );
	}

	update_vertices( map );
	made_graph = true;
}

Vertex& Simple_Hero::get_vertex( int x, int y ) {
	if( !made_graph ) {
		printf( "Called get_vertex without initializing graph\n" );
		exit(0);
	}

	return graph[x][y];

}

int Simple_Hero::select_neighbor( GraphMap* map, int x, int y ) {

	return 0;
}

int Simple_Hero::where_go( GraphMap* map, int x1, int y1, int x2, int y2 ) {
	queue<Vertex> v_q;

	if( x1 < 0 || y1 < 0 ) {
		printf( "Invalid coordinates for source vertex in where_go - (%d, %d)\n", x1, y1 );
		exit(0);
	}

	if( x2 < 0 || y2 < 0 ) {
		printf( "Invalid coordinates for dest vertex in where_go - (%d, %d)\n", x2, y2 );
		exit(0);
	}

	Vertex source ( x1, y1 );
	Vertex target ( x2, y2 );
	Vertex popped, temp;

	v_q.push( source );

	while( !v_q.empty() ) {
		popped = v_q.front();

		if( popped.visited ) {
			v_q.pop();
			continue;
		}

		for( int i = 0; i < map->getNumNeighbors( popped.x, popped.y ); i++ ) {
			int a, b;
			map->getNeighbor( popped.x, popped.y, i, a, b );
			temp = get_vertex( a, b );
			temp.prev = &popped;

			if( temp == target ) {
				break;
			}

			if( !temp.visited ) {
				temp.visited = true;
				v_q.push( temp );
			}
		}

		v_q.pop();

	}

	while( !(*temp.prev == source ) ) {
		temp = *temp.prev;
	}

	for( int i = 0; i < map->getNumNeighbors( temp.prev->x, temp.prev->y ); i++ ) {
		int a, b;
		map->getNeighbor( temp.prev->x, temp.prev->y, i, a, b );
		Vertex check( a, b );

		if( check == source ) {
			return i;
		}
	}

	return -1;
}

Simple_Hero::~Simple_Hero() {}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2015 The Brick Authors.

#include "brick/brick_app.h"

#include <unistd.h>
#include <gtk/gtk.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <X11/Xlib.h>
#include <X11/extensions/scrnsaver.h>

#include "third-party/json/json.h"
#include "include/wrapper/cef_helpers.h"
#include "include/cef_app.h"
#include "brick/indicator/indicator.h"
#include "brick/client_handler.h"
#include "brick/client_app.h"
#include "brick/window_util.h"
#include "brick/helper.h"
#include "brick/platform_util.h"
#include "brick/external_interface/dbus_protocol.h"

#undef Status   // Definition conflicts with cef_urlrequest.h
#undef Success  // Definition conflicts with cef_message_router.h

namespace {
  const int kMainWindowWidth = 914;
  const int kMainWindowHeight = 454;
  const int32 kIdleTimeout = 600000L;
  const unsigned long kIdleCheckInterval = 10000;
  std::string kAppIcons[] = {"brick16.png", "brick32.png", "brick48.png", "brick128.png", "brick256.png"};
  std::string szWorkingDir;  // The current working directory
  std::string startupLocale;

  bool
  GetWorkingDir(std::string& dir) {
    char buff[1024];

    // Retrieve the executable path.
    ssize_t len = readlink("/proc/self/exe", buff, sizeof(buff)-1);
    if (len == -1)
      return false;

    buff[len] = 0;
    dir = std::string(buff);
    // Remove the executable name from the path.
    dir = dir.substr(0, dir.find_last_of("/"));

    return true;
  }

  bool
  EnsureSystemDirectoryExists() {
    return (
       platform_util::MakeDirectory(platform_util::GetCacheDir() + "/" + APP_COMMON_NAME)
        && platform_util::MakeDirectory(platform_util::GetCacheDir() + "/" + APP_COMMON_NAME)
    );
  }

  bool
  EnsureSingleInstance() {
    std::string lock_file = platform_util::GetCacheDir() + "/" + APP_COMMON_NAME + "/run.lock";
    int fd = open(lock_file.c_str(), O_CREAT, 0600);
    if (fd == -1)
      return true;

    return flock(fd, LOCK_EX|LOCK_NB) == 0;
  }

  gboolean
  CheckUserIdle(gpointer data) {
    /* Query xscreensaver */
    static XScreenSaverInfo *mit_info = NULL;
    static int has_extension = -1;
    int event_base, error_base;

    if (has_extension == -1)
      has_extension = XScreenSaverQueryExtension(GDK_DISPLAY(), &event_base, &error_base);

    if (!has_extension) {
      LOG(WARNING) << "XScreenSaver extension not found, 'auto away' feature is  being disabled.";
      // Don't call this function anymore
      return false;
    }

    CefRefPtr<ClientHandler> handler = ClientHandler::GetInstance();
    if (!handler)
      return true;

    if (!handler->IsIdlePending())
      return true;

    if (mit_info == NULL)
      mit_info = XScreenSaverAllocInfo();

    XScreenSaverQueryInfo(GDK_DISPLAY(), GDK_ROOT_WINDOW(), mit_info);
    if (mit_info->idle >= kIdleTimeout && !handler->IsIdle()) {
      UserAwayEvent e(true);
      EventBus::FireEvent(e);
    } else if (mit_info->idle < kIdleTimeout && handler->IsIdle()) {
      UserAwayEvent e(false);
      EventBus::FireEvent(e);
    }

    return true;
  }

  void
  GdkEventDispatcher(GdkEvent *event, gpointer data) {
    BrowserWindow *window = window_util::LookupBrowserWindow(event);
    if (window != NULL) {
      // We have event for browser window
      window->OnNativeEvent(event);
    }
    gtk_main_do_event(event);
  }

  bool
  CheckLogFileSize(CefString path) {
    std::string file_path = path;
    struct stat stat_buf;
    int rc = stat(file_path.c_str(), &stat_buf);

    if (rc == 0 && stat_buf.st_size > 1024*1024*20) {
      unlink(file_path.c_str());
      LOG(INFO) << "Runtime log is too big (" << stat_buf.st_size << ") and will be truncated";
    }

    return true;
  }
}  // namespace

// static
const char*
BrickApp::GetConfigHome() {
  return g_get_user_config_dir();
}

// static
std::string
BrickApp::FindUserConfig(const char* name) {
  std::string result = "";
  char* filename = g_build_filename(g_get_user_config_dir(), APP_COMMON_NAME, name, NULL);
  if (platform_util::IsPathExists(filename))
    result = filename;
  g_free(filename);
  return result;
}

// static
std::string
BrickApp::FindSystemConfig(const char* name) {
  std::string result = "";
  const gchar* const *dirs = g_get_system_config_dirs();
  const gchar* const *dir;
  char* filename;

  for (dir = dirs; *dir; ++dir) {
    filename = g_build_filename(*dir, APP_COMMON_NAME, name, NULL);
    if (platform_util::IsPathExists(filename)) {
      result = filename;
      g_free(filename);
      break;
    }
    g_free(filename);
  }

  return result;
}

const std::string
BrickApp::GetCurrentLanguage(bool withTags) {
  if (startupLocale.empty())
    startupLocale = pango_language_to_string(gtk_get_default_language());

  std::string::size_type pos;
  // withTags = true means returns "en_US" for locale "en_US.UTF-8"
  // Otherwise returns only language "en"
  if (withTags)
    pos = startupLocale.find('.');
  else
    pos = startupLocale.find_first_of("-_");

  std::string result;
  if (pos != std::string::npos)
    result = startupLocale.substr(0, pos);
  else
    result = startupLocale;

  if (result.empty() || result == "c")
    result = withTags ? "en-us" : "en";  // Use "en" by default

  // TODO(buglloc): R&D, maybe we may using locale as-is, without stripping?
  return result;
}

const std::string
BrickApp::GetAcceptLanguageList() {
  std::ostringstream result;
  result << GetCurrentLanguage(true) << "," << GetCurrentLanguage(false);
  return result.str();
}

void
TerminationSignalHandler(int signatl) {
  CefRefPtr<ClientHandler> handler = ClientHandler::GetInstance();
  if (handler) {
    handler->Shutdown(false);
  } else {
    CefQuitMessageLoop();
  }
}

int main(int argc, char* argv[]) {
  // TODO(buglloc): Good refactoring candidate!

  setlocale(LC_ALL, "");
  CefMainArgs main_args(argc, argv);
  CefRefPtr<ClientApp> app(new ClientApp);

  // Execute the secondary process, if any.
  int exit_code = CefExecuteProcess(main_args, app.get(), NULL);
  if (exit_code >= 0)
    return exit_code;

  if (!EnsureSystemDirectoryExists()) {
    printf("Can't create system directories");
    return 1;
  }

  CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
  command_line->InitFromArgv(argc, (const char* const *) argv);

  GetWorkingDir(szWorkingDir);
  AppSettings app_settings = AppSettings::InitByJson(
     BrickApp::GetSystemConfig()
  );
  app_settings.UpdateByJson(
     BrickApp::GetUserConfig()
  );
  app_settings.UpdateByCommandLine(
      command_line
  );

  app_settings.resource_dir = helper::BaseDir(szWorkingDir) + "/resources/";
  CefSettings cef_settings = BrickApp::GetCefSettings(szWorkingDir, app_settings);

  LOG_IF(WARNING,
     !CheckLogFileSize(&cef_settings.log_file)) << "Can't check runtie log file size";

  // If we have D-BUS - check single running with it (and call App::Present)
  // Otherwise - fallback to EnsureSingleInstance with flock
  CefRefPtr<DBusProtocol> dbus = NULL;
  if (app_settings.external_api) {
    dbus = new DBusProtocol;
    if (dbus->Init() && !dbus->isSingleInstance()) {
      // We already own D-BUS session in another instance
      dbus->BringAnotherInstance();
      printf("Another instance is already running.");
      return 0;
    }
  } else if (!EnsureSingleInstance()) {
    printf("Another instance is already running.");
    return 0;
  }

  CefRefPtr<AccountManager> account_manager(new AccountManager);
  account_manager->Init(
    std::string(BrickApp::GetConfigHome()) + "/" + APP_COMMON_NAME + "/accounts.json"
  );

  CefRefPtr<CacheManager> cache_manager(new CacheManager);
  cache_manager->Init(
    platform_util::GetCacheDir() + "/" + APP_COMMON_NAME + "/app/"
  );
  // TODO(buglloc): need to be safer?
  cache_manager->CleanUpCache();

  gtk_init(0, NULL);
  // TODO(buglloc): Maybe better to set scale in main_args here?
  app->SetDeviceScaleFactor(window_util::GetDeviceScaleFactor());
  // Initialize CEF.
  CefInitialize(main_args, cef_settings, app.get(), NULL);

  gdk_event_handler_set(GdkEventDispatcher, NULL, NULL);
  window_util::InitHooks();

  if (app_settings.auto_away) {
    gtk_timeout_add(kIdleCheckInterval, CheckUserIdle, NULL);
  }

  // Set default windows icon. Important to do this before any GTK window created!
  GList *icons = NULL;
  std::string icon_path = app_settings.resource_dir + "/app_icons/";
  int icons_count = sizeof(kAppIcons) / sizeof(kAppIcons[0]);
  for (int i = 0; i < icons_count; ++i) {
    GdkPixbuf *icon = gdk_pixbuf_new_from_file((icon_path + kAppIcons[i]).c_str(), NULL);
    if (!icon)
      continue;
    icons = g_list_append(icons, icon);
  }
  window_util::SetDefaultIcons(icons);

  // Create the handler.
  CefRefPtr<ClientHandler> client_handler(new ClientHandler);
  client_handler->SetAppSettings(app_settings);
  client_handler->SetAccountManager(account_manager);
  client_handler->SetNotificationManager(new NotificationManager);
  client_handler->SetCacheManager(cache_manager);

  // Initialize status icon
  CefRefPtr<BrickIndicator> brick_indicator(new BrickIndicator(app_settings.resource_dir + "/indicator/icons/"));
  brick_indicator->UseExtendedStatus(app_settings.extended_status);
  client_handler->SetIndicatorHandle(brick_indicator);

  client_handler->Initialize();

  std::string startup_url = account_manager->GetCurrentAccount()->GetBaseUrl();
  if (account_manager->GetCurrentAccount()->IsExisted()) {
    // Login to our account
    startup_url += "internals/web/pages/portal-loader#login=yes";
  } else {
    // Otherwise let's show error page
    startup_url += "internals/web/pages/home";
  }

  // Setup main window size & positions
  CefRect screen_rect = window_util::GetDefaultScreenRect();
  CefWindowInfo window_info;
  window_info.width = static_cast<unsigned int>(kMainWindowWidth * window_util::GetDeviceScaleFactor());
  window_info.height = static_cast<unsigned int>(kMainWindowHeight * window_util::GetDeviceScaleFactor());
  window_info.x = screen_rect.x + (screen_rect.width - window_info.width) / 2;
  window_info.y = screen_rect.y + (screen_rect.height - window_info.height) / 2;

  // Create browser
  CefBrowserHost::CreateBrowserSync(
     window_info, client_handler.get(),
     startup_url, BrickApp::GetBrowserSettings(szWorkingDir, app_settings), NULL);

  // Install a signal handler so we clean up after ourselves.
  signal(SIGINT, TerminationSignalHandler);
  signal(SIGTERM, TerminationSignalHandler);

  CefRunMessageLoop();

  CefShutdown();

  return 0;
}
<commit_msg>Fixed signed and unsigned comparison in AFK timer<commit_after>// Copyright (c) 2015 The Brick Authors.

#include "brick/brick_app.h"

#include <unistd.h>
#include <gtk/gtk.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <X11/Xlib.h>
#include <X11/extensions/scrnsaver.h>

#include "third-party/json/json.h"
#include "include/wrapper/cef_helpers.h"
#include "include/cef_app.h"
#include "brick/indicator/indicator.h"
#include "brick/client_handler.h"
#include "brick/client_app.h"
#include "brick/window_util.h"
#include "brick/helper.h"
#include "brick/platform_util.h"
#include "brick/external_interface/dbus_protocol.h"

#undef Status   // Definition conflicts with cef_urlrequest.h
#undef Success  // Definition conflicts with cef_message_router.h

namespace {
  const int kMainWindowWidth = 914;
  const int kMainWindowHeight = 454;
  const unsigned long kIdleTimeout = 600000L;
  const unsigned long kIdleCheckInterval = 10000L;
  std::string kAppIcons[] = {"brick16.png", "brick32.png", "brick48.png", "brick128.png", "brick256.png"};
  std::string szWorkingDir;  // The current working directory
  std::string startupLocale;

  bool
  GetWorkingDir(std::string& dir) {
    char buff[1024];

    // Retrieve the executable path.
    ssize_t len = readlink("/proc/self/exe", buff, sizeof(buff)-1);
    if (len == -1)
      return false;

    buff[len] = 0;
    dir = std::string(buff);
    // Remove the executable name from the path.
    dir = dir.substr(0, dir.find_last_of("/"));

    return true;
  }

  bool
  EnsureSystemDirectoryExists() {
    return (
       platform_util::MakeDirectory(platform_util::GetCacheDir() + "/" + APP_COMMON_NAME)
        && platform_util::MakeDirectory(platform_util::GetCacheDir() + "/" + APP_COMMON_NAME)
    );
  }

  bool
  EnsureSingleInstance() {
    std::string lock_file = platform_util::GetCacheDir() + "/" + APP_COMMON_NAME + "/run.lock";
    int fd = open(lock_file.c_str(), O_CREAT, 0600);
    if (fd == -1)
      return true;

    return flock(fd, LOCK_EX|LOCK_NB) == 0;
  }

  gboolean
  CheckUserIdle(gpointer data) {
    /* Query xscreensaver */
    static XScreenSaverInfo *mit_info = NULL;
    static int has_extension = -1;
    int event_base, error_base;

    if (has_extension == -1)
      has_extension = XScreenSaverQueryExtension(GDK_DISPLAY(), &event_base, &error_base);

    if (!has_extension) {
      LOG(WARNING) << "XScreenSaver extension not found, 'auto away' feature is  being disabled.";
      // Don't call this function anymore
      return false;
    }

    CefRefPtr<ClientHandler> handler = ClientHandler::GetInstance();
    if (!handler)
      return true;

    if (!handler->IsIdlePending())
      return true;

    if (mit_info == NULL)
      mit_info = XScreenSaverAllocInfo();

    XScreenSaverQueryInfo(GDK_DISPLAY(), GDK_ROOT_WINDOW(), mit_info);
    if (mit_info->idle >= kIdleTimeout && !handler->IsIdle()) {
      UserAwayEvent e(true);
      EventBus::FireEvent(e);
    } else if (mit_info->idle < kIdleTimeout && handler->IsIdle()) {
      UserAwayEvent e(false);
      EventBus::FireEvent(e);
    }

    return true;
  }

  void
  GdkEventDispatcher(GdkEvent *event, gpointer data) {
    BrowserWindow *window = window_util::LookupBrowserWindow(event);
    if (window != NULL) {
      // We have event for browser window
      window->OnNativeEvent(event);
    }
    gtk_main_do_event(event);
  }

  bool
  CheckLogFileSize(CefString path) {
    std::string file_path = path;
    struct stat stat_buf;
    int rc = stat(file_path.c_str(), &stat_buf);

    if (rc == 0 && stat_buf.st_size > 1024*1024*20) {
      unlink(file_path.c_str());
      LOG(INFO) << "Runtime log is too big (" << stat_buf.st_size << ") and will be truncated";
    }

    return true;
  }
}  // namespace

// static
const char*
BrickApp::GetConfigHome() {
  return g_get_user_config_dir();
}

// static
std::string
BrickApp::FindUserConfig(const char* name) {
  std::string result = "";
  char* filename = g_build_filename(g_get_user_config_dir(), APP_COMMON_NAME, name, NULL);
  if (platform_util::IsPathExists(filename))
    result = filename;
  g_free(filename);
  return result;
}

// static
std::string
BrickApp::FindSystemConfig(const char* name) {
  std::string result = "";
  const gchar* const *dirs = g_get_system_config_dirs();
  const gchar* const *dir;
  char* filename;

  for (dir = dirs; *dir; ++dir) {
    filename = g_build_filename(*dir, APP_COMMON_NAME, name, NULL);
    if (platform_util::IsPathExists(filename)) {
      result = filename;
      g_free(filename);
      break;
    }
    g_free(filename);
  }

  return result;
}

const std::string
BrickApp::GetCurrentLanguage(bool withTags) {
  if (startupLocale.empty())
    startupLocale = pango_language_to_string(gtk_get_default_language());

  std::string::size_type pos;
  // withTags = true means returns "en_US" for locale "en_US.UTF-8"
  // Otherwise returns only language "en"
  if (withTags)
    pos = startupLocale.find('.');
  else
    pos = startupLocale.find_first_of("-_");

  std::string result;
  if (pos != std::string::npos)
    result = startupLocale.substr(0, pos);
  else
    result = startupLocale;

  if (result.empty() || result == "c")
    result = withTags ? "en-us" : "en";  // Use "en" by default

  // TODO(buglloc): R&D, maybe we may using locale as-is, without stripping?
  return result;
}

const std::string
BrickApp::GetAcceptLanguageList() {
  std::ostringstream result;
  result << GetCurrentLanguage(true) << "," << GetCurrentLanguage(false);
  return result.str();
}

void
TerminationSignalHandler(int signatl) {
  CefRefPtr<ClientHandler> handler = ClientHandler::GetInstance();
  if (handler) {
    handler->Shutdown(false);
  } else {
    CefQuitMessageLoop();
  }
}

int main(int argc, char* argv[]) {
  // TODO(buglloc): Good refactoring candidate!

  setlocale(LC_ALL, "");
  CefMainArgs main_args(argc, argv);
  CefRefPtr<ClientApp> app(new ClientApp);

  // Execute the secondary process, if any.
  int exit_code = CefExecuteProcess(main_args, app.get(), NULL);
  if (exit_code >= 0)
    return exit_code;

  if (!EnsureSystemDirectoryExists()) {
    printf("Can't create system directories");
    return 1;
  }

  CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
  command_line->InitFromArgv(argc, (const char* const *) argv);

  GetWorkingDir(szWorkingDir);
  AppSettings app_settings = AppSettings::InitByJson(
     BrickApp::GetSystemConfig()
  );
  app_settings.UpdateByJson(
     BrickApp::GetUserConfig()
  );
  app_settings.UpdateByCommandLine(
      command_line
  );

  app_settings.resource_dir = helper::BaseDir(szWorkingDir) + "/resources/";
  CefSettings cef_settings = BrickApp::GetCefSettings(szWorkingDir, app_settings);

  LOG_IF(WARNING,
     !CheckLogFileSize(&cef_settings.log_file)) << "Can't check runtie log file size";

  // If we have D-BUS - check single running with it (and call App::Present)
  // Otherwise - fallback to EnsureSingleInstance with flock
  CefRefPtr<DBusProtocol> dbus = NULL;
  if (app_settings.external_api) {
    dbus = new DBusProtocol;
    if (dbus->Init() && !dbus->isSingleInstance()) {
      // We already own D-BUS session in another instance
      dbus->BringAnotherInstance();
      printf("Another instance is already running.");
      return 0;
    }
  } else if (!EnsureSingleInstance()) {
    printf("Another instance is already running.");
    return 0;
  }

  CefRefPtr<AccountManager> account_manager(new AccountManager);
  account_manager->Init(
    std::string(BrickApp::GetConfigHome()) + "/" + APP_COMMON_NAME + "/accounts.json"
  );

  CefRefPtr<CacheManager> cache_manager(new CacheManager);
  cache_manager->Init(
    platform_util::GetCacheDir() + "/" + APP_COMMON_NAME + "/app/"
  );
  // TODO(buglloc): need to be safer?
  cache_manager->CleanUpCache();

  gtk_init(0, NULL);
  // TODO(buglloc): Maybe better to set scale in main_args here?
  app->SetDeviceScaleFactor(window_util::GetDeviceScaleFactor());
  // Initialize CEF.
  CefInitialize(main_args, cef_settings, app.get(), NULL);

  gdk_event_handler_set(GdkEventDispatcher, NULL, NULL);
  window_util::InitHooks();

  if (app_settings.auto_away) {
    gtk_timeout_add(kIdleCheckInterval, CheckUserIdle, NULL);
  }

  // Set default windows icon. Important to do this before any GTK window created!
  GList *icons = NULL;
  std::string icon_path = app_settings.resource_dir + "/app_icons/";
  int icons_count = sizeof(kAppIcons) / sizeof(kAppIcons[0]);
  for (int i = 0; i < icons_count; ++i) {
    GdkPixbuf *icon = gdk_pixbuf_new_from_file((icon_path + kAppIcons[i]).c_str(), NULL);
    if (!icon)
      continue;
    icons = g_list_append(icons, icon);
  }
  window_util::SetDefaultIcons(icons);

  // Create the handler.
  CefRefPtr<ClientHandler> client_handler(new ClientHandler);
  client_handler->SetAppSettings(app_settings);
  client_handler->SetAccountManager(account_manager);
  client_handler->SetNotificationManager(new NotificationManager);
  client_handler->SetCacheManager(cache_manager);

  // Initialize status icon
  CefRefPtr<BrickIndicator> brick_indicator(new BrickIndicator(app_settings.resource_dir + "/indicator/icons/"));
  brick_indicator->UseExtendedStatus(app_settings.extended_status);
  client_handler->SetIndicatorHandle(brick_indicator);

  client_handler->Initialize();

  std::string startup_url = account_manager->GetCurrentAccount()->GetBaseUrl();
  if (account_manager->GetCurrentAccount()->IsExisted()) {
    // Login to our account
    startup_url += "internals/web/pages/portal-loader#login=yes";
  } else {
    // Otherwise let's show error page
    startup_url += "internals/web/pages/home";
  }

  // Setup main window size & positions
  CefRect screen_rect = window_util::GetDefaultScreenRect();
  CefWindowInfo window_info;
  window_info.width = static_cast<unsigned int>(kMainWindowWidth * window_util::GetDeviceScaleFactor());
  window_info.height = static_cast<unsigned int>(kMainWindowHeight * window_util::GetDeviceScaleFactor());
  window_info.x = screen_rect.x + (screen_rect.width - window_info.width) / 2;
  window_info.y = screen_rect.y + (screen_rect.height - window_info.height) / 2;

  // Create browser
  CefBrowserHost::CreateBrowserSync(
     window_info, client_handler.get(),
     startup_url, BrickApp::GetBrowserSettings(szWorkingDir, app_settings), NULL);

  // Install a signal handler so we clean up after ourselves.
  signal(SIGINT, TerminationSignalHandler);
  signal(SIGTERM, TerminationSignalHandler);

  CefRunMessageLoop();

  CefShutdown();

  return 0;
}
<|endoftext|>