<commit_before>/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <boost/circular_buffer.hpp>
#include "latency.hh"
#include <cmath>
#include "core/timer.hh"
#include <iostream>
namespace utils {
/**
 * An exponentially-weighted moving average.
 */
class moving_average {
    double _alpha = 0;
    bool _initialized = false;
    latency_counter::duration _tick_interval;
    uint64_t _count = 0;
    double _rate = 0;
public:
    moving_average(latency_counter::duration interval, latency_counter::duration tick_interval) :
        _tick_interval(tick_interval) {
        _alpha = 1 - std::exp(-std::chrono::duration_cast<std::chrono::seconds>(tick_interval).count()/
                static_cast<double>(std::chrono::duration_cast<std::chrono::seconds>(interval).count()));
    }

    void add(uint64_t val = 1) {
        _count += val;
    }

    void update() {
        double instant_rate = _count / static_cast<double>(std::chrono::duration_cast<std::chrono::seconds>(_tick_interval).count());
        if (_initialized) {
            _rate += (_alpha * (instant_rate - _rate));
        } else {
            _rate = instant_rate;
            _initialized = true;
        }
        _count = 0;
    }

    bool is_initilized() const {
        return _initialized;
    }

    double rate() const {
        if (is_initilized()) {
            return _rate;
        }
        return 0;
    }
};

class ihistogram {
public:
    // count holds all the events
    int64_t count;
    // total holds only the events we sample
    int64_t total;
    int64_t min;
    int64_t max;
    int64_t sum;
    int64_t started;
    double mean;
    double variance;
    int64_t sample_mask;
    boost::circular_buffer<int64_t> sample;
    ihistogram(size_t size = 1024, int64_t _sample_mask = 0x80)
            : count(0), total(0), min(0), max(0), sum(0), started(0), mean(0), variance(0),
              sample_mask(_sample_mask), sample(
                    size) {
    }
    void mark(int64_t value) {
        if (total == 0 || value < min) {
            min = value;
        }
        if (total == 0 || value > max) {
            max = value;
        }
        if (total == 0) {
            mean = value;
            variance = 0;
        } else {
            double old_m = mean;
            double old_s = variance;

            mean = ((double)(sum + value)) / (total + 1);
            variance = old_s + ((value - old_m) * (value - mean));
        }
        sum += value;
        total++;
        count++;
        sample.push_back(value);
    }

    void mark(latency_counter& lc) {
        if (lc.is_start()) {
            mark(lc.stop().latency_in_nano());
        } else {
            count++;
        }
    }

    /**
     * Return true if the current event should be sample.
     * In the typical case, there is no need to use this method
     * Call set_latency, that would start a latency object if needed.
     */
    bool should_sample() const {
        return total == 0 || (started & sample_mask);
    }
    /**
     * Set the latency according to the sample rate.
     */
    ihistogram& set_latency(latency_counter& lc) {
        if (should_sample()) {
            lc.start();
        }
        started++;
        return *this;
    }

    /**
     * Allow to use the histogram as a counter
     * Increment the total number of events without
     * sampling the value.
     */
    ihistogram& inc() {
        count++;
        return *this;
    }

    int64_t pending() const {
        return started - count;
    }

    inline double pow2(double a) {
        return a * a;
    }

    ihistogram& operator +=(const ihistogram& o) {
        if (count == 0) {
            *this = o;
        } else if (o.count > 0) {
            if (min > o.min) {
                min = o.min;
            }
            if (max < o.max) {
                max = o.max;
            }
            double ncount = count + o.count;
            sum += o.sum;
            double a = count / ncount;
            double b = o.count / ncount;

            double m = a * mean + b * o.mean;

            variance = (variance + pow2(m - mean)) * a
                    + (o.variance + pow2(o.mean - mean)) * b;
            mean = m;
            count += o.count;
            total += o.total;
            for (auto i : o.sample) {
                sample.push_back(i);
            }
        }
        return *this;
    }

    int64_t estimated_sum() const {
        return mean * count;
    }

    friend ihistogram operator +(ihistogram a, const ihistogram& b);
};

inline ihistogram operator +(ihistogram a, const ihistogram& b) {
    a += b;
    return a;
}

struct rate_moving_average {
    uint64_t count = 0;
    double rates[3] = {0};
    double mean_rate = 0;
    rate_moving_average& operator +=(const rate_moving_average& o) {
        count += o.count;
        mean_rate += o.mean_rate;
        for (int i=0; i<3; i++) {
            rates[i] += o.rates[i];
        }
        return *this;
    }
    friend rate_moving_average operator+ (rate_moving_average a, const rate_moving_average& b);
};

inline rate_moving_average operator+ (rate_moving_average a, const rate_moving_average& b) {
    a += b;
    return a;
}

class timed_rate_moving_average {
    static constexpr latency_counter::duration tick_interval() {
        return std::chrono::seconds(10);
    }
    moving_average rates[3] = {{std::chrono::minutes(1), tick_interval()}, {std::chrono::minutes(5), tick_interval()}, {std::chrono::minutes(15), tick_interval()}};
    latency_counter::time_point start_time;
    timer<> _timer;

public:
    // _count is public so the collectd will be able to use it.
    // for all other cases use the count() method
    uint64_t _count = 0;
    timed_rate_moving_average() : start_time(latency_counter::now()), _timer([this] {
        update();
    }) {
        _timer.arm_periodic(tick_interval());
    }

    void mark(uint64_t n = 1) {
        _count += n;
        for (int i = 0; i < 3; i++) {
            rates[i].add(n);
        }
    }

    rate_moving_average rate() const {
        rate_moving_average res;
        if (_count > 0) {
            double elapsed = std::chrono::duration_cast<std::chrono::seconds>(latency_counter::now() - start_time).count();
            res.mean_rate = (_count / elapsed);
        }
        res.count = _count;
        for (int i = 0; i < 3; i++) {
            res.rates[i] = rates[i].rate();
        }
        return res;
    }

    void update() {
        for (int i = 0; i < 3; i++) {
            rates[i].update();
        }
    }

    uint64_t count() const {
        return _count;
    }
};

struct rate_moving_average_and_histogram {
    ihistogram hist;
    rate_moving_average rate;

    rate_moving_average_and_histogram& operator +=(const rate_moving_average_and_histogram& o) {
        hist += o.hist;
        rate += o.rate;
        return *this;
    }
    friend rate_moving_average_and_histogram operator +(rate_moving_average_and_histogram a, const rate_moving_average_and_histogram& b);
};

inline rate_moving_average_and_histogram operator +(rate_moving_average_and_histogram a, const rate_moving_average_and_histogram& b) {
    a += b;
    return a;
}

/**
 * A timer metric which aggregates timing durations and provides duration statistics, plus
 * throughput statistics via meter
 */
class timed_rate_moving_average_and_histogram {
public:
    ihistogram hist;
    timed_rate_moving_average met;
    timed_rate_moving_average_and_histogram() = default;
    timed_rate_moving_average_and_histogram(timed_rate_moving_average_and_histogram&&) = default;
    timed_rate_moving_average_and_histogram(const timed_rate_moving_average_and_histogram&) = default;
    timed_rate_moving_average_and_histogram(size_t size, int64_t _sample_mask = 0x80) : hist(size, _sample_mask) {}
    timed_rate_moving_average_and_histogram& operator=(const timed_rate_moving_average_and_histogram&) = default;
    void mark(int duration) {
        if (duration >= 0) {
            hist.mark(duration);
            met.mark();
        }
    }

    void mark(latency_counter& lc) {
        hist.mark(lc);
        met.mark();
    }

    void set_latency(latency_counter& lc) {
        hist.set_latency(lc);
    }

    rate_moving_average_and_histogram rate() const {
        rate_moving_average_and_histogram res;
        res.hist = hist;
        res.rate = met.rate();
        return res;
    }
};

}
<commit_msg>histogram: fix reporting units<commit_after>/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <boost/circular_buffer.hpp>
#include "latency.hh"
#include <cmath>
#include "core/timer.hh"
#include <iostream>
namespace utils {
/**
 * An exponentially-weighted moving average.
 */
class moving_average {
    double _alpha = 0;
    bool _initialized = false;
    latency_counter::duration _tick_interval;
    uint64_t _count = 0;
    double _rate = 0;
public:
    moving_average(latency_counter::duration interval, latency_counter::duration tick_interval) :
        _tick_interval(tick_interval) {
        _alpha = 1 - std::exp(-std::chrono::duration_cast<std::chrono::seconds>(tick_interval).count()/
                static_cast<double>(std::chrono::duration_cast<std::chrono::seconds>(interval).count()));
    }

    void add(uint64_t val = 1) {
        _count += val;
    }

    void update() {
        double instant_rate = _count / static_cast<double>(std::chrono::duration_cast<std::chrono::seconds>(_tick_interval).count());
        if (_initialized) {
            _rate += (_alpha * (instant_rate - _rate));
        } else {
            _rate = instant_rate;
            _initialized = true;
        }
        _count = 0;
    }

    bool is_initilized() const {
        return _initialized;
    }

    double rate() const {
        if (is_initilized()) {
            return _rate;
        }
        return 0;
    }
};

template <typename Unit>
class basic_ihistogram {
public:
    // count holds all the events
    int64_t count;
    // total holds only the events we sample
    int64_t total;
    int64_t min;
    int64_t max;
    int64_t sum;
    int64_t started;
    double mean;
    double variance;
    int64_t sample_mask;
    boost::circular_buffer<int64_t> sample;
    basic_ihistogram(size_t size = 1024, int64_t _sample_mask = 0x80)
            : count(0), total(0), min(0), max(0), sum(0), started(0), mean(0), variance(0),
              sample_mask(_sample_mask), sample(
                    size) {
    }
    void mark(int64_t ns_value) {
        auto value = std::chrono::duration_cast<Unit>(std::chrono::nanoseconds(ns_value)).count();
        if (total == 0 || value < min) {
            min = value;
        }
        if (total == 0 || value > max) {
            max = value;
        }
        if (total == 0) {
            mean = value;
            variance = 0;
        } else {
            double old_m = mean;
            double old_s = variance;

            mean = ((double)(sum + value)) / (total + 1);
            variance = old_s + ((value - old_m) * (value - mean));
        }
        sum += value;
        total++;
        count++;
        sample.push_back(value);
    }

    void mark(latency_counter& lc) {
        if (lc.is_start()) {
            mark(lc.stop().latency_in_nano());
        } else {
            count++;
        }
    }

    /**
     * Return true if the current event should be sample.
     * In the typical case, there is no need to use this method
     * Call set_latency, that would start a latency object if needed.
     */
    bool should_sample() const {
        return total == 0 || (started & sample_mask);
    }
    /**
     * Set the latency according to the sample rate.
     */
    basic_ihistogram& set_latency(latency_counter& lc) {
        if (should_sample()) {
            lc.start();
        }
        started++;
        return *this;
    }

    /**
     * Allow to use the histogram as a counter
     * Increment the total number of events without
     * sampling the value.
     */
    basic_ihistogram& inc() {
        count++;
        return *this;
    }

    int64_t pending() const {
        return started - count;
    }

    inline double pow2(double a) {
        return a * a;
    }

    basic_ihistogram& operator +=(const basic_ihistogram& o) {
        if (count == 0) {
            *this = o;
        } else if (o.count > 0) {
            if (min > o.min) {
                min = o.min;
            }
            if (max < o.max) {
                max = o.max;
            }
            double ncount = count + o.count;
            sum += o.sum;
            double a = count / ncount;
            double b = o.count / ncount;

            double m = a * mean + b * o.mean;

            variance = (variance + pow2(m - mean)) * a
                    + (o.variance + pow2(o.mean - mean)) * b;
            mean = m;
            count += o.count;
            total += o.total;
            for (auto i : o.sample) {
                sample.push_back(i);
            }
        }
        return *this;
    }

    int64_t estimated_sum() const {
        return mean * count;
    }

    template <typename U>
    friend basic_ihistogram<U> operator +(basic_ihistogram<U> a, const basic_ihistogram<U>& b);
};

template <typename Unit>
inline basic_ihistogram<Unit> operator +(basic_ihistogram<Unit> a, const basic_ihistogram<Unit>& b) {
    a += b;
    return a;
}

using ihistogram = basic_ihistogram<std::chrono::microseconds>;

struct rate_moving_average {
    uint64_t count = 0;
    double rates[3] = {0};
    double mean_rate = 0;
    rate_moving_average& operator +=(const rate_moving_average& o) {
        count += o.count;
        mean_rate += o.mean_rate;
        for (int i=0; i<3; i++) {
            rates[i] += o.rates[i];
        }
        return *this;
    }
    friend rate_moving_average operator+ (rate_moving_average a, const rate_moving_average& b);
};

inline rate_moving_average operator+ (rate_moving_average a, const rate_moving_average& b) {
    a += b;
    return a;
}

class timed_rate_moving_average {
    static constexpr latency_counter::duration tick_interval() {
        return std::chrono::seconds(10);
    }
    moving_average rates[3] = {{std::chrono::minutes(1), tick_interval()}, {std::chrono::minutes(5), tick_interval()}, {std::chrono::minutes(15), tick_interval()}};
    latency_counter::time_point start_time;
    timer<> _timer;

public:
    // _count is public so the collectd will be able to use it.
    // for all other cases use the count() method
    uint64_t _count = 0;
    timed_rate_moving_average() : start_time(latency_counter::now()), _timer([this] {
        update();
    }) {
        _timer.arm_periodic(tick_interval());
    }

    void mark(uint64_t n = 1) {
        _count += n;
        for (int i = 0; i < 3; i++) {
            rates[i].add(n);
        }
    }

    rate_moving_average rate() const {
        rate_moving_average res;
        if (_count > 0) {
            double elapsed = std::chrono::duration_cast<std::chrono::seconds>(latency_counter::now() - start_time).count();
            res.mean_rate = (_count / elapsed);
        }
        res.count = _count;
        for (int i = 0; i < 3; i++) {
            res.rates[i] = rates[i].rate();
        }
        return res;
    }

    void update() {
        for (int i = 0; i < 3; i++) {
            rates[i].update();
        }
    }

    uint64_t count() const {
        return _count;
    }
};

struct rate_moving_average_and_histogram {
    ihistogram hist;
    rate_moving_average rate;

    rate_moving_average_and_histogram& operator +=(const rate_moving_average_and_histogram& o) {
        hist += o.hist;
        rate += o.rate;
        return *this;
    }
    friend rate_moving_average_and_histogram operator +(rate_moving_average_and_histogram a, const rate_moving_average_and_histogram& b);
};

inline rate_moving_average_and_histogram operator +(rate_moving_average_and_histogram a, const rate_moving_average_and_histogram& b) {
    a += b;
    return a;
}

/**
 * A timer metric which aggregates timing durations and provides duration statistics, plus
 * throughput statistics via meter
 */
class timed_rate_moving_average_and_histogram {
public:
    ihistogram hist;
    timed_rate_moving_average met;
    timed_rate_moving_average_and_histogram() = default;
    timed_rate_moving_average_and_histogram(timed_rate_moving_average_and_histogram&&) = default;
    timed_rate_moving_average_and_histogram(const timed_rate_moving_average_and_histogram&) = default;
    timed_rate_moving_average_and_histogram(size_t size, int64_t _sample_mask = 0x80) : hist(size, _sample_mask) {}
    timed_rate_moving_average_and_histogram& operator=(const timed_rate_moving_average_and_histogram&) = default;
    void mark(int duration) {
        if (duration >= 0) {
            hist.mark(duration);
            met.mark();
        }
    }

    void mark(latency_counter& lc) {
        hist.mark(lc);
        met.mark();
    }

    void set_latency(latency_counter& lc) {
        hist.set_latency(lc);
    }

    rate_moving_average_and_histogram rate() const {
        rate_moving_average_and_histogram res;
        res.hist = hist;
        res.rate = met.rate();
        return res;
    }
};

}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016 zScale Technology GmbH <legal@zscale.io>
 * Authors:
 *   - Paul Asmuth <paul@zscale.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include "eventql/eventql.h"
#include "eventql/util/logging.h"
#include <eventql/db/CompactionStrategy.h>
#include <eventql/db/LSMTableIndex.h>
#include <eventql/io/cstable/cstable_writer.h>
#include <eventql/util/io/fileutil.h>

namespace eventql {

SimpleCompactionStrategy::SimpleCompactionStrategy(
    RefPtr<Partition> partition,
    LSMTableIndexCache* idx_cache,
    size_t num_tables_soft_limit,
    size_t num_tables_hard_limit) :
    partition_(partition),
    idx_cache_(idx_cache),
    num_tables_soft_limit_(num_tables_soft_limit),
    num_tables_hard_limit_(num_tables_hard_limit) {}

bool SimpleCompactionStrategy::compact(
    const Vector<LSMTableRef>& input,
    Vector<LSMTableRef>* output) {
  if (input.empty()) {
    return false;
  }

  if (!needsCompaction(input)) {
    return false;
  }

  HashMap<SHA1Hash, uint64_t> vmap;
  for (auto tbl = input.rbegin(); tbl != input.rend(); ++tbl) {
    auto idx = idx_cache_->lookup(
        FileUtil::joinPaths(partition_->getRelativePath(), tbl->filename()));
    idx->list(&vmap);
  }

  auto table = partition_->getTable();
  auto base_path = partition_->getAbsolutePath();
  auto cstable_schema = cstable::TableSchema::fromProtobuf(*table->schema());
  auto cstable_schema_ext = cstable_schema;
  cstable_schema_ext.addBool("__lsm_is_update", false);
  cstable_schema_ext.addString("__lsm_id", false);
  cstable_schema_ext.addUnsignedInteger("__lsm_version", false);
  cstable_schema_ext.addUnsignedInteger("__lsm_sequence", false);

  auto cstable_filename = Random::singleton()->hex64();
  auto cstable_filepath = FileUtil::joinPaths(base_path, cstable_filename);

  auto cstable = cstable::CSTableWriter::createFile(
      cstable_filepath + ".cst",
      cstable::BinaryFormatVersion::v0_2_0,
      cstable_schema_ext);

  auto is_update_col = cstable->getColumnWriter("__lsm_is_update");
  auto id_col = cstable->getColumnWriter("__lsm_id");
  auto version_col = cstable->getColumnWriter("__lsm_version");
  auto sequence_col = cstable->getColumnWriter("__lsm_sequence");
  size_t rows_written = 0;
  size_t rows_skipped = 0;

  for (const auto& tbl : input) {
    auto input_cstable_file = FileUtil::joinPaths(
        base_path,
        tbl.filename() + ".cst");

    if (!FileUtil::exists(input_cstable_file)) {
      logWarning("evqld", "missing table file: $0", input_cstable_file);
      continue;
    }

    try {
      auto input_cstable = cstable::CSTableReader::openFile(input_cstable_file);
      auto input_id_col = input_cstable->getColumnReader("__lsm_id");
      auto input_version_col = input_cstable->getColumnReader("__lsm_version");
      auto input_sequence_col = input_cstable->getColumnReader("__lsm_sequence");
      RefPtr<cstable::ColumnReader> input_skip_col;
      if (tbl.has_skiplist()) {
        input_skip_col = input_cstable->getColumnReader("__lsm_skip");
      }

      Vector<Pair<
          RefPtr<cstable::ColumnReader>,
          RefPtr<cstable::ColumnWriter>>> columns;

      auto flat_columns = cstable_schema.flatColumns();
      for (const auto& col : flat_columns) {
        if (input_cstable->hasColumn(col.column_name)) {
          columns.emplace_back(
              input_cstable->getColumnReader(col.column_name),
              cstable->getColumnWriter(col.column_name));
        } else {
          if (col.dlevel_max == 0) {
            RAISE(
                kIllegalStateError,
                "can't merge CSTables after a new required column was added");
          }

          columns.emplace_back(
              nullptr,
              cstable->getColumnWriter(col.column_name));
        }
      }

      auto nrecords = input_cstable->numRecords();
      for (size_t i = 0; i < nrecords; ++i) {
        uint64_t rlvl;
        uint64_t dlvl;

        String id_str;
        input_id_col->readString(&rlvl, &dlvl, &id_str);
        SHA1Hash id(id_str.data(), id_str.size());

        uint64_t version;
        input_version_col->readUnsignedInt(&rlvl, &dlvl, &version);

        uint64_t sequence;
        input_sequence_col->readUnsignedInt(&rlvl, &dlvl, &sequence);

        bool skip = false;
        if (input_skip_col.get()) {
          input_skip_col->readBoolean(&rlvl, &dlvl, &skip);
        }

        const auto& vmap_iter = vmap.find(id);
        if (vmap_iter == vmap.end()) {
          RAISE(kIllegalStateError, "invalid cstable contents");
        }

        if (skip || version != vmap_iter->second) {
          for (auto& col : columns) {
            if (col.first.get()) {
              do {
                col.first->skipValue();
              } while (col.first->nextRepetitionLevel() > 0);
            }
          }

          ++rows_skipped;
        } else {
          is_update_col->writeBoolean(0, 0, false);
          id_col->writeString(0, 0, id_str);
          version_col->writeUnsignedInt(0, 0, version);
          sequence_col->writeUnsignedInt(0, 0, sequence);

          for (auto& col : columns) {
            if (col.first.get()) {
              do {
                col.first->copyValue(col.second.get());
              } while (col.first->nextRepetitionLevel() > 0);
            } else {
              col.second->writeNull(0, 0);
            }
          }

          cstable->addRow();
          ++rows_written;
        }
      }
    } catch (const std::exception& e) {
      logError(
          "evqld",
          "error while compacting table: $0 -- $1",
          input_cstable_file,
          e.what());

      throw e;
    }
  }

  cstable->commit();

  OrderedMap<SHA1Hash, uint64_t> vmap_ordered;
  for (const auto& p : vmap) {
    vmap_ordered.emplace(p);
  }
  LSMTableIndex::write(vmap_ordered, cstable_filepath + ".idx");

  auto snap = partition_->getSnapshot();
  logDebug(
      "z1.core",
      "Compacting partition $4/$5/$6 (rows_written=$0, rows_skipped=$1 sequence=$2..$3)",
      rows_written,
      rows_skipped,
      input.begin()->first_sequence(),
      input.rbegin()->last_sequence(),
      snap->state.tsdb_namespace(),
      snap->state.table_key(),
      snap->key.toString());

  LSMTableRef tbl_ref;
  tbl_ref.set_filename(cstable_filename);
  tbl_ref.set_first_sequence(input.begin()->first_sequence());
  tbl_ref.set_last_sequence(input.rbegin()->last_sequence());
  tbl_ref.set_size_bytes(FileUtil::size(cstable_filepath + ".cst"));
  tbl_ref.set_has_skiplist(false);
  output->emplace_back(tbl_ref);

  return true;
}

bool SimpleCompactionStrategy::needsCompaction(
    const Vector<LSMTableRef>& tables) {
  return tables.size() > num_tables_soft_limit_;
}

bool SimpleCompactionStrategy::needsUrgentCompaction(
    const Vector<LSMTableRef>& tables) {
  return tables.size() > num_tables_hard_limit_;
}

} // namespace eventql

<commit_msg>allow compaction for all partitions<commit_after>/**
 * Copyright (c) 2016 zScale Technology GmbH <legal@zscale.io>
 * Authors:
 *   - Paul Asmuth <paul@zscale.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include "eventql/eventql.h"
#include "eventql/util/logging.h"
#include <eventql/db/CompactionStrategy.h>
#include <eventql/db/LSMTableIndex.h>
#include <eventql/io/cstable/cstable_writer.h>
#include <eventql/util/io/fileutil.h>

namespace eventql {

SimpleCompactionStrategy::SimpleCompactionStrategy(
    RefPtr<Partition> partition,
    LSMTableIndexCache* idx_cache,
    size_t num_tables_soft_limit,
    size_t num_tables_hard_limit) :
    partition_(partition),
    idx_cache_(idx_cache),
    num_tables_soft_limit_(num_tables_soft_limit),
    num_tables_hard_limit_(num_tables_hard_limit) {}

bool SimpleCompactionStrategy::compact(
    const Vector<LSMTableRef>& input,
    Vector<LSMTableRef>* output) {
  if (input.empty()) {
    return false;
  }

  //if (!needsCompaction(input)) {
  //  return false;
  //}

  HashMap<SHA1Hash, uint64_t> vmap;
  for (auto tbl = input.rbegin(); tbl != input.rend(); ++tbl) {
    auto idx = idx_cache_->lookup(
        FileUtil::joinPaths(partition_->getRelativePath(), tbl->filename()));
    idx->list(&vmap);
  }

  auto table = partition_->getTable();
  auto base_path = partition_->getAbsolutePath();
  auto cstable_schema = cstable::TableSchema::fromProtobuf(*table->schema());
  auto cstable_schema_ext = cstable_schema;
  cstable_schema_ext.addBool("__lsm_is_update", false);
  cstable_schema_ext.addString("__lsm_id", false);
  cstable_schema_ext.addUnsignedInteger("__lsm_version", false);
  cstable_schema_ext.addUnsignedInteger("__lsm_sequence", false);

  auto cstable_filename = Random::singleton()->hex64();
  auto cstable_filepath = FileUtil::joinPaths(base_path, cstable_filename);

  auto cstable = cstable::CSTableWriter::createFile(
      cstable_filepath + ".cst",
      cstable::BinaryFormatVersion::v0_2_0,
      cstable_schema_ext);

  auto is_update_col = cstable->getColumnWriter("__lsm_is_update");
  auto id_col = cstable->getColumnWriter("__lsm_id");
  auto version_col = cstable->getColumnWriter("__lsm_version");
  auto sequence_col = cstable->getColumnWriter("__lsm_sequence");
  size_t rows_written = 0;
  size_t rows_skipped = 0;

  for (const auto& tbl : input) {
    auto input_cstable_file = FileUtil::joinPaths(
        base_path,
        tbl.filename() + ".cst");

    if (!FileUtil::exists(input_cstable_file)) {
      logWarning("evqld", "missing table file: $0", input_cstable_file);
      continue;
    }

    try {
      auto input_cstable = cstable::CSTableReader::openFile(input_cstable_file);
      auto input_id_col = input_cstable->getColumnReader("__lsm_id");
      auto input_version_col = input_cstable->getColumnReader("__lsm_version");
      auto input_sequence_col = input_cstable->getColumnReader("__lsm_sequence");
      RefPtr<cstable::ColumnReader> input_skip_col;
      if (tbl.has_skiplist()) {
        input_skip_col = input_cstable->getColumnReader("__lsm_skip");
      }

      Vector<Pair<
          RefPtr<cstable::ColumnReader>,
          RefPtr<cstable::ColumnWriter>>> columns;

      auto flat_columns = cstable_schema.flatColumns();
      for (const auto& col : flat_columns) {
        if (input_cstable->hasColumn(col.column_name)) {
          columns.emplace_back(
              input_cstable->getColumnReader(col.column_name),
              cstable->getColumnWriter(col.column_name));
        } else {
          if (col.dlevel_max == 0) {
            RAISE(
                kIllegalStateError,
                "can't merge CSTables after a new required column was added");
          }

          columns.emplace_back(
              nullptr,
              cstable->getColumnWriter(col.column_name));
        }
      }

      auto nrecords = input_cstable->numRecords();
      for (size_t i = 0; i < nrecords; ++i) {
        uint64_t rlvl;
        uint64_t dlvl;

        String id_str;
        input_id_col->readString(&rlvl, &dlvl, &id_str);
        SHA1Hash id(id_str.data(), id_str.size());

        uint64_t version;
        input_version_col->readUnsignedInt(&rlvl, &dlvl, &version);

        uint64_t sequence;
        input_sequence_col->readUnsignedInt(&rlvl, &dlvl, &sequence);

        bool skip = false;
        if (input_skip_col.get()) {
          input_skip_col->readBoolean(&rlvl, &dlvl, &skip);
        }

        const auto& vmap_iter = vmap.find(id);
        if (vmap_iter == vmap.end()) {
          RAISE(kIllegalStateError, "invalid cstable contents");
        }

        if (skip || version != vmap_iter->second) {
          for (auto& col : columns) {
            if (col.first.get()) {
              do {
                col.first->skipValue();
              } while (col.first->nextRepetitionLevel() > 0);
            }
          }

          ++rows_skipped;
        } else {
          is_update_col->writeBoolean(0, 0, false);
          id_col->writeString(0, 0, id_str);
          version_col->writeUnsignedInt(0, 0, version);
          sequence_col->writeUnsignedInt(0, 0, sequence);

          for (auto& col : columns) {
            if (col.first.get()) {
              do {
                col.first->copyValue(col.second.get());
              } while (col.first->nextRepetitionLevel() > 0);
            } else {
              col.second->writeNull(0, 0);
            }
          }

          cstable->addRow();
          ++rows_written;
        }
      }
    } catch (const std::exception& e) {
      logError(
          "evqld",
          "error while compacting table: $0 -- $1",
          input_cstable_file,
          e.what());

      throw e;
    }
  }

  cstable->commit();

  OrderedMap<SHA1Hash, uint64_t> vmap_ordered;
  for (const auto& p : vmap) {
    vmap_ordered.emplace(p);
  }
  LSMTableIndex::write(vmap_ordered, cstable_filepath + ".idx");

  auto snap = partition_->getSnapshot();
  logDebug(
      "z1.core",
      "Compacting partition $4/$5/$6 (rows_written=$0, rows_skipped=$1 sequence=$2..$3)",
      rows_written,
      rows_skipped,
      input.begin()->first_sequence(),
      input.rbegin()->last_sequence(),
      snap->state.tsdb_namespace(),
      snap->state.table_key(),
      snap->key.toString());

  LSMTableRef tbl_ref;
  tbl_ref.set_filename(cstable_filename);
  tbl_ref.set_first_sequence(input.begin()->first_sequence());
  tbl_ref.set_last_sequence(input.rbegin()->last_sequence());
  tbl_ref.set_size_bytes(FileUtil::size(cstable_filepath + ".cst"));
  tbl_ref.set_has_skiplist(false);
  output->emplace_back(tbl_ref);

  return true;
}

bool SimpleCompactionStrategy::needsCompaction(
    const Vector<LSMTableRef>& tables) {
  return tables.size() > num_tables_soft_limit_;
}

bool SimpleCompactionStrategy::needsUrgentCompaction(
    const Vector<LSMTableRef>& tables) {
  return tables.size() > num_tables_hard_limit_;
}

} // namespace eventql

<|endoftext|>


<commit_before>server {
    listen       80;
    server_name  shop.cc;

    root /Users/hy0kl/work/iwebshop;
    access_log  logs/shop.access.log  main;

    location / {
        index index.php index.html index.htm;

        # 对 IE 进行限速
        if ($http_user_agent ~ "MSIE") {
            limit_rate 1k;
        }

        # 如果没有解析出 request_filename 则重写到单一入口
        if (!-e $request_filename) {
            rewrite ^/(.*)  /index.php last; # last 重写后继续路由到 server
        }
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }

    # 不记录 favicon.ico 错误日志
    location ~ (favicon.ico){
        log_not_found off;
        expires 100d;
        access_log off;
    }

    # 静态文件设置过期时间
    location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
        expires max;
        break;
    }

    # 静态文件代理
    location ~ /static/ {
        rewrite "^/static/(.*)$" /static/$1 break;  # break 重写后不再续费路由
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        include        fastcgi_params;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_index  index.php;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}
<commit_msg>加入nginx负载均衡配置参考实例.<commit_after>upstream shop.cc {
    server 127.0.0.1:9000;
}

server {
    listen       80;
    server_name  shop.cc;

    root /Users/hy0kl/work/iwebshop;
    access_log  logs/shop.access.log  main;

    location / {
        index index.php index.html index.htm;

        # 对 IE 进行限速
        if ($http_user_agent ~ "MSIE") {
            limit_rate 1k;
        }

        # 如果没有解析出 request_filename 则重写到单一入口
        if (!-e $request_filename) {
            rewrite ^/(.*)  /index.php last; # last 重写后继续路由到 server
        }
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }

    # 不记录 favicon.ico 错误日志
    location ~ (favicon.ico){
        log_not_found off;
        expires 100d;
        access_log off;
    }

    # 静态文件设置过期时间
    location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
        expires max;
        break;
    }

    # 静态文件代理
    location ~ /static/ {
        rewrite "^/static/(.*)$" /static/$1 break;  # break 重写后不再续费路由
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
        include        fastcgi_params;
        fastcgi_pass   shop.cc;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_index  index.php;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}
<|endoftext|>


<commit_before>// [WriteFile Name=ChangeSublayerVisibility, Category=Layers]
// [Legal]
// Copyright 2016 Esri.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// [Legal]

#include "ChangeSublayerVisibility.h"

#include "Map.h"
#include "MapQuickView.h"
#include "Basemap.h"
#include "ArcGISMapImageLayer.h"
#include "ArcGISSublayerListModel.h"
#include <QUrl>

using namespace Esri::ArcGISRuntime;

ChangeSublayerVisibility::ChangeSublayerVisibility(QQuickItem* parent) :
    QQuickItem(parent),
    m_map(nullptr),
    m_mapView(nullptr),
    m_mapImageLayer(nullptr),
    m_sublayerModel(nullptr)
{
}

ChangeSublayerVisibility::~ChangeSublayerVisibility()
{
}

void ChangeSublayerVisibility::componentComplete()
{
    QQuickItem::componentComplete();

    // find QML MapView component
    m_mapView = findChild<MapQuickView*>("mapView");

    // create a new map instance
    m_map = new Map(Basemap::topographic(this), this);

    // add the map image layer
    m_mapImageLayer = new ArcGISMapImageLayer(QUrl("http://sampleserver6.arcgisonline.com/arcgis/rest/services/SampleWorldCities/MapServer"), this);
    m_map->operationalLayers()->append(m_mapImageLayer);

    // set map on the map view
    m_mapView->setMap(m_map);

    // set the map image layer's sublayer list model to the Q_PROPERTY
    m_sublayerModel = m_mapImageLayer->mapImageSublayers();
    sublayerModelChanged();
}

ArcGISSublayerListModel* ChangeSublayerVisibility::sublayerModel()
{
    return m_sublayerModel;
}

<commit_msg>setting initial viewpoint<commit_after>// [WriteFile Name=ChangeSublayerVisibility, Category=Layers]
// [Legal]
// Copyright 2016 Esri.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// [Legal]

#include "ChangeSublayerVisibility.h"

#include "Map.h"
#include "MapQuickView.h"
#include "Basemap.h"
#include "ArcGISMapImageLayer.h"
#include "ArcGISSublayerListModel.h"
#include "Point.h"
#include "Viewpoint.h"
#include "SpatialReference.h"
#include <QUrl>

using namespace Esri::ArcGISRuntime;

ChangeSublayerVisibility::ChangeSublayerVisibility(QQuickItem* parent) :
    QQuickItem(parent),
    m_map(nullptr),
    m_mapView(nullptr),
    m_mapImageLayer(nullptr),
    m_sublayerModel(nullptr)
{
}

ChangeSublayerVisibility::~ChangeSublayerVisibility()
{
}

void ChangeSublayerVisibility::componentComplete()
{
    QQuickItem::componentComplete();

    // find QML MapView component
    m_mapView = findChild<MapQuickView*>("mapView");

    // create a new map instance
    m_map = new Map(Basemap::topographic(this), this);
    m_map->setInitialViewpoint(Viewpoint(Point(-11e6, 6e6, SpatialReference(102100)), 9e7));

    // add the map image layer
    m_mapImageLayer = new ArcGISMapImageLayer(QUrl("http://sampleserver6.arcgisonline.com/arcgis/rest/services/SampleWorldCities/MapServer"), this);
    m_map->operationalLayers()->append(m_mapImageLayer);

    // set map on the map view
    m_mapView->setMap(m_map);

    // set the map image layer's sublayer list model to the Q_PROPERTY
    m_sublayerModel = m_mapImageLayer->mapImageSublayers();
    sublayerModelChanged();
}

ArcGISSublayerListModel* ChangeSublayerVisibility::sublayerModel()
{
    return m_sublayerModel;
}

<|endoftext|>


<commit_before>#include <core/stdafx.h>
#include <core/smartview/GlobalObjectId.h>
#include <core/interpret/flags.h>
#include <core/mapi/extraPropTags.h>
#include <core/utility/strings.h>

namespace smartview
{
	// clang-format off
	static const BYTE s_rgbSPlus[] =
	{
		0x04, 0x00, 0x00, 0x00,
		0x82, 0x00, 0xE0, 0x00,
		0x74, 0xC5, 0xB7, 0x10,
		0x1A, 0x82, 0xE0, 0x08,
	};
	// clang-format on

	void GlobalObjectId::parse()
	{
		m_Id = blockBytes::parse(parser, 16);

		const auto b1 = blockT<BYTE>::parse(parser);
		const auto b2 = blockT<BYTE>::parse(parser);
		m_Year =
			blockT<WORD>::create(static_cast<WORD>(*b1 << 8 | *b2), b1->getSize() + b2->getSize(), b1->getOffset());

		m_Month = blockT<BYTE>::parse(parser);
		const auto szFlags = flags::InterpretFlags(flagGlobalObjectIdMonth, *m_Month);

		m_Day = blockT<BYTE>::parse(parser);

		m_CreationTime = blockT<FILETIME>::parse(parser);
		m_X = blockT<LARGE_INTEGER>::parse(parser);
		m_dwSize = blockT<DWORD>::parse(parser);
		m_lpData = blockBytes::parse(parser, *m_dwSize, _MaxBytes);
	}

	void GlobalObjectId::parseBlocks()
	{
		setText(L"Global Object ID");
		if (m_Id->isSet())
		{
			auto id = create(L"Byte Array ID =");
			addChild(id);
			id->addChild(m_Id);

			if (m_Id->equal(sizeof s_rgbSPlus, s_rgbSPlus))
			{
				m_Id->addHeader(L"= s_rgbSPlus");
			}
			else
			{
				m_Id->addHeader(L"= Unknown GUID");
			}
		}

		addChild(m_Year, L"Year: 0x%1!04X! = %1!d!", m_Year->getData());

		addChild(
			m_Month,
			L"Month: 0x%1!02X! = %1!d! = %2!ws!",
			m_Month->getData(),
			flags::InterpretFlags(flagGlobalObjectIdMonth, *m_Month).c_str());

		addChild(m_Day, L"Day: 0x%1!02X! = %1!d!", m_Day->getData());

		std::wstring propString;
		std::wstring altPropString;
		strings::FileTimeToString(*m_CreationTime, propString, altPropString);
		addChild(
			m_CreationTime,
			L"Creation Time = 0x%1!08X!:0x%2!08X! = %3!ws!",
			m_CreationTime->getData().dwHighDateTime,
			m_CreationTime->getData().dwLowDateTime,
			propString.c_str());

		addChild(m_X, L"X: 0x%1!08X!:0x%2!08X!", m_X->getData().HighPart, m_X->getData().LowPart);
		addChild(m_dwSize, L"Size: 0x%1!02X! = %1!d!", m_dwSize->getData());

		if (m_lpData->size())
		{
			addLabeledChild(L"Data =", m_lpData);
		}
	}
} // namespace smartview<commit_msg>make another label<commit_after>#include <core/stdafx.h>
#include <core/smartview/GlobalObjectId.h>
#include <core/interpret/flags.h>
#include <core/mapi/extraPropTags.h>
#include <core/utility/strings.h>

namespace smartview
{
	// clang-format off
	static const BYTE s_rgbSPlus[] =
	{
		0x04, 0x00, 0x00, 0x00,
		0x82, 0x00, 0xE0, 0x00,
		0x74, 0xC5, 0xB7, 0x10,
		0x1A, 0x82, 0xE0, 0x08,
	};
	// clang-format on

	void GlobalObjectId::parse()
	{
		m_Id = blockBytes::parse(parser, 16);

		const auto b1 = blockT<BYTE>::parse(parser);
		const auto b2 = blockT<BYTE>::parse(parser);
		m_Year =
			blockT<WORD>::create(static_cast<WORD>(*b1 << 8 | *b2), b1->getSize() + b2->getSize(), b1->getOffset());

		m_Month = blockT<BYTE>::parse(parser);
		const auto szFlags = flags::InterpretFlags(flagGlobalObjectIdMonth, *m_Month);

		m_Day = blockT<BYTE>::parse(parser);

		m_CreationTime = blockT<FILETIME>::parse(parser);
		m_X = blockT<LARGE_INTEGER>::parse(parser);
		m_dwSize = blockT<DWORD>::parse(parser);
		m_lpData = blockBytes::parse(parser, *m_dwSize, _MaxBytes);
	}

	void GlobalObjectId::parseBlocks()
	{
		setText(L"Global Object ID");
		if (m_Id->isSet())
		{
			addLabeledChild(L"Byte Array ID =", m_Id);

			if (m_Id->equal(sizeof s_rgbSPlus, s_rgbSPlus))
			{
				m_Id->addHeader(L"= s_rgbSPlus");
			}
			else
			{
				m_Id->addHeader(L"= Unknown GUID");
			}
		}

		addChild(m_Year, L"Year: 0x%1!04X! = %1!d!", m_Year->getData());

		addChild(
			m_Month,
			L"Month: 0x%1!02X! = %1!d! = %2!ws!",
			m_Month->getData(),
			flags::InterpretFlags(flagGlobalObjectIdMonth, *m_Month).c_str());

		addChild(m_Day, L"Day: 0x%1!02X! = %1!d!", m_Day->getData());

		std::wstring propString;
		std::wstring altPropString;
		strings::FileTimeToString(*m_CreationTime, propString, altPropString);
		addChild(
			m_CreationTime,
			L"Creation Time = 0x%1!08X!:0x%2!08X! = %3!ws!",
			m_CreationTime->getData().dwHighDateTime,
			m_CreationTime->getData().dwLowDateTime,
			propString.c_str());

		addChild(m_X, L"X: 0x%1!08X!:0x%2!08X!", m_X->getData().HighPart, m_X->getData().LowPart);
		addChild(m_dwSize, L"Size: 0x%1!02X! = %1!d!", m_dwSize->getData());

		if (m_lpData->size())
		{
			addLabeledChild(L"Data =", m_lpData);
		}
	}
} // namespace smartview<|endoftext|>


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

#include "oned/ODCode128Writer.h"
#include "oned/ODWriterHelper.h"
#include "oned/ODCode128Patterns.h"

#include <list>
#include <numeric>

namespace ZXing {
namespace OneD {

static const int CODE_START_B = 104;
static const int CODE_START_C = 105;
static const int CODE_CODE_B = 100;
static const int CODE_CODE_C = 99;
static const int CODE_STOP = 106;

// Dummy characters used to specify control characters in input
static const auto ESCAPE_FNC_1 = L'\u00f1';
static const auto ESCAPE_FNC_2 = L'\u00f2';
static const auto ESCAPE_FNC_3 = L'\u00f3';
static const auto ESCAPE_FNC_4 = L'\u00f4';

static const int CODE_FNC_1 = 102;   // Code A, Code B, Code C
static const int CODE_FNC_2 = 97;    // Code A, Code B
static const int CODE_FNC_3 = 96;    // Code A, Code B
static const int CODE_FNC_4_B = 100; // Code B

 // Results of minimal lookahead for code C
enum class CType {
	UNCODABLE,
	ONE_DIGIT,
	TWO_DIGITS,
	FNC_1
};

static CType FindCType(const std::wstring& value, int start)
{
	int last = static_cast<int>(value.length());
	if (start >= last) {
		return CType::UNCODABLE;
	}
	wchar_t c = value[start];
	if (c == ESCAPE_FNC_1) {
		return CType::FNC_1;
	}
	if (c < '0' || c > '9') {
		return CType::UNCODABLE;
	}
	if (start + 1 >= last) {
		return CType::ONE_DIGIT;
	}
	c = value[start + 1];
	if (c < '0' || c > '9') {
		return CType::ONE_DIGIT;
	}
	return CType::TWO_DIGITS;
}

static int ChooseCode(const std::wstring& value, int start, int oldCode)
{
	CType lookahead = FindCType(value, start);
	if (lookahead == CType::UNCODABLE || lookahead == CType::ONE_DIGIT) {
		return CODE_CODE_B; // no choice
	}
	if (oldCode == CODE_CODE_C) { // can continue in code C
		return CODE_CODE_C;
	}
	if (oldCode == CODE_CODE_B) {
		if (lookahead == CType::FNC_1) {
			return CODE_CODE_B; // can continue in code B
		}
		// Seen two consecutive digits, see what follows
		lookahead = FindCType(value, start + 2);
		if (lookahead == CType::UNCODABLE || lookahead == CType::ONE_DIGIT) {
			return CODE_CODE_B; // not worth switching now
		}
		if (lookahead == CType::FNC_1) { // two digits, then FNC_1...
			lookahead = FindCType(value, start + 3);
			if (lookahead == CType::TWO_DIGITS) { // then two more digits, switch
				return CODE_CODE_C;
			}
			else {
				return CODE_CODE_B; // otherwise not worth switching
			}
		}
		// At this point, there are at least 4 consecutive digits.
		// Look ahead to choose whether to switch now or on the next round.
		int index = start + 4;
		while ((lookahead = FindCType(value, index)) == CType::TWO_DIGITS) {
			index += 2;
		}
		if (lookahead == CType::ONE_DIGIT) { // odd number of digits, switch later
			return CODE_CODE_B;
		}
		return CODE_CODE_C; // even number of digits, switch now
	}
	// Here oldCode == 0, which means we are choosing the initial code
	if (lookahead == CType::FNC_1) { // ignore FNC_1
		lookahead = FindCType(value, start + 1);
	}
	if (lookahead == CType::TWO_DIGITS) { // at least two digits, start in code C
		return CODE_CODE_C;
	}
	return CODE_CODE_B;
}

void
Code128Writer::encode(const std::wstring& contents, int width, int height, BitMatrix& output) const
{
	// Check length
	int length = static_cast<int>(contents.length());
	if (length < 1 || length > 80) {
		throw std::invalid_argument("Contents length should be between 1 and 80 characters");
	}

	// Check content
	for (int i = 0; i < length; ++i) {
		int c = contents[i];
		if (c < ' ' || c > '~') {
			switch (c) {
			case ESCAPE_FNC_1:
			case ESCAPE_FNC_2:
			case ESCAPE_FNC_3:
			case ESCAPE_FNC_4:
				break;
			default:
				throw std::invalid_argument("Bad character in input: " + static_cast<char>(c));
			}
		}
	}

	std::list<std::vector<int>> patterns; // temporary storage for patterns
	int checkSum = 0;
	int checkWeight = 1;
	int codeSet = 0; // selected code (CODE_CODE_B or CODE_CODE_C)
	int position = 0; // position in contents

	while (position < length) {
		//Select code to use
		int newCodeSet = ChooseCode(contents, position, codeSet);

		//Get the pattern index
		int patternIndex;
		if (newCodeSet == codeSet) {
			// Encode the current character
			// First handle escapes
			switch (contents[position]) {
			case ESCAPE_FNC_1:
				patternIndex = CODE_FNC_1;
				break;
			case ESCAPE_FNC_2:
				patternIndex = CODE_FNC_2;
				break;
			case ESCAPE_FNC_3:
				patternIndex = CODE_FNC_3;
				break;
			case ESCAPE_FNC_4:
				patternIndex = CODE_FNC_4_B; // FIXME if this ever outputs Code A
				break;
			default:
				// Then handle normal characters otherwise
				if (codeSet == CODE_CODE_B) {
					patternIndex = contents[position] - ' ';
				}
				else { // CODE_CODE_C
					patternIndex = (contents[position] - '0') * 10 + (position+1 < length ? contents[position+1] - '0' : 0);
					position++; // Also incremented below
				}
			}
			position++;
		}
		else {
			// Should we change the current code?
			// Do we have a code set?
			if (codeSet == 0) {
				// No, we don't have a code set
				if (newCodeSet == CODE_CODE_B) {
					patternIndex = CODE_START_B;
				}
				else {
					// CODE_CODE_C
					patternIndex = CODE_START_C;
				}
			}
			else {
				// Yes, we have a code set
				patternIndex = newCodeSet;
			}
			codeSet = newCodeSet;
		}

		// Get the pattern
		patterns.push_back(Code128::CODE_PATTERNS[patternIndex]);

		// Compute checksum
		checkSum += patternIndex * checkWeight;
		if (position != 0) {
			checkWeight++;
		}
	}

	// Compute and append checksum
	checkSum %= 103;
	patterns.push_back(Code128::CODE_PATTERNS[checkSum]);

	// Append stop code
	patterns.push_back(Code128::CODE_PATTERNS[CODE_STOP]);

	// Compute code width
	int codeWidth = 0;
	for (const std::vector<int>& pattern : patterns) {
		codeWidth += std::accumulate(pattern.begin(), pattern.end(), 0);
	}

	// Compute result
	std::vector<bool> result(codeWidth, false);
	int pos = 0;
	for (const std::vector<int>& pattern : patterns) {
		pos += WriterHelper::AppendPattern(result, pos, pattern, true);
	}

	WriterHelper::RenderResult(result, width, height, _sidesMargin >= 0 ? _sidesMargin : 10, output);
}

} // OneD
} // ZXing
<commit_msg>Fix wrong string concatenation<commit_after>/*
* Copyright 2016 Huy Cuong Nguyen
* Copyright 2016 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "oned/ODCode128Writer.h"
#include "oned/ODWriterHelper.h"
#include "oned/ODCode128Patterns.h"

#include <list>
#include <numeric>

namespace ZXing {
namespace OneD {

static const int CODE_START_B = 104;
static const int CODE_START_C = 105;
static const int CODE_CODE_B = 100;
static const int CODE_CODE_C = 99;
static const int CODE_STOP = 106;

// Dummy characters used to specify control characters in input
static const auto ESCAPE_FNC_1 = L'\u00f1';
static const auto ESCAPE_FNC_2 = L'\u00f2';
static const auto ESCAPE_FNC_3 = L'\u00f3';
static const auto ESCAPE_FNC_4 = L'\u00f4';

static const int CODE_FNC_1 = 102;   // Code A, Code B, Code C
static const int CODE_FNC_2 = 97;    // Code A, Code B
static const int CODE_FNC_3 = 96;    // Code A, Code B
static const int CODE_FNC_4_B = 100; // Code B

 // Results of minimal lookahead for code C
enum class CType {
	UNCODABLE,
	ONE_DIGIT,
	TWO_DIGITS,
	FNC_1
};

static CType FindCType(const std::wstring& value, int start)
{
	int last = static_cast<int>(value.length());
	if (start >= last) {
		return CType::UNCODABLE;
	}
	wchar_t c = value[start];
	if (c == ESCAPE_FNC_1) {
		return CType::FNC_1;
	}
	if (c < '0' || c > '9') {
		return CType::UNCODABLE;
	}
	if (start + 1 >= last) {
		return CType::ONE_DIGIT;
	}
	c = value[start + 1];
	if (c < '0' || c > '9') {
		return CType::ONE_DIGIT;
	}
	return CType::TWO_DIGITS;
}

static int ChooseCode(const std::wstring& value, int start, int oldCode)
{
	CType lookahead = FindCType(value, start);
	if (lookahead == CType::UNCODABLE || lookahead == CType::ONE_DIGIT) {
		return CODE_CODE_B; // no choice
	}
	if (oldCode == CODE_CODE_C) { // can continue in code C
		return CODE_CODE_C;
	}
	if (oldCode == CODE_CODE_B) {
		if (lookahead == CType::FNC_1) {
			return CODE_CODE_B; // can continue in code B
		}
		// Seen two consecutive digits, see what follows
		lookahead = FindCType(value, start + 2);
		if (lookahead == CType::UNCODABLE || lookahead == CType::ONE_DIGIT) {
			return CODE_CODE_B; // not worth switching now
		}
		if (lookahead == CType::FNC_1) { // two digits, then FNC_1...
			lookahead = FindCType(value, start + 3);
			if (lookahead == CType::TWO_DIGITS) { // then two more digits, switch
				return CODE_CODE_C;
			}
			else {
				return CODE_CODE_B; // otherwise not worth switching
			}
		}
		// At this point, there are at least 4 consecutive digits.
		// Look ahead to choose whether to switch now or on the next round.
		int index = start + 4;
		while ((lookahead = FindCType(value, index)) == CType::TWO_DIGITS) {
			index += 2;
		}
		if (lookahead == CType::ONE_DIGIT) { // odd number of digits, switch later
			return CODE_CODE_B;
		}
		return CODE_CODE_C; // even number of digits, switch now
	}
	// Here oldCode == 0, which means we are choosing the initial code
	if (lookahead == CType::FNC_1) { // ignore FNC_1
		lookahead = FindCType(value, start + 1);
	}
	if (lookahead == CType::TWO_DIGITS) { // at least two digits, start in code C
		return CODE_CODE_C;
	}
	return CODE_CODE_B;
}

void
Code128Writer::encode(const std::wstring& contents, int width, int height, BitMatrix& output) const
{
	// Check length
	int length = static_cast<int>(contents.length());
	if (length < 1 || length > 80) {
		throw std::invalid_argument("Contents length should be between 1 and 80 characters");
	}

	// Check content
	for (int i = 0; i < length; ++i) {
		int c = contents[i];
		if (c < ' ' || c > '~') {
			switch (c) {
			case ESCAPE_FNC_1:
			case ESCAPE_FNC_2:
			case ESCAPE_FNC_3:
			case ESCAPE_FNC_4:
				break;
			default:
				throw std::invalid_argument(std::string("Bad character in input: ") + static_cast<char>(c));
			}
		}
	}

	std::list<std::vector<int>> patterns; // temporary storage for patterns
	int checkSum = 0;
	int checkWeight = 1;
	int codeSet = 0; // selected code (CODE_CODE_B or CODE_CODE_C)
	int position = 0; // position in contents

	while (position < length) {
		//Select code to use
		int newCodeSet = ChooseCode(contents, position, codeSet);

		//Get the pattern index
		int patternIndex;
		if (newCodeSet == codeSet) {
			// Encode the current character
			// First handle escapes
			switch (contents[position]) {
			case ESCAPE_FNC_1:
				patternIndex = CODE_FNC_1;
				break;
			case ESCAPE_FNC_2:
				patternIndex = CODE_FNC_2;
				break;
			case ESCAPE_FNC_3:
				patternIndex = CODE_FNC_3;
				break;
			case ESCAPE_FNC_4:
				patternIndex = CODE_FNC_4_B; // FIXME if this ever outputs Code A
				break;
			default:
				// Then handle normal characters otherwise
				if (codeSet == CODE_CODE_B) {
					patternIndex = contents[position] - ' ';
				}
				else { // CODE_CODE_C
					patternIndex = (contents[position] - '0') * 10 + (position+1 < length ? contents[position+1] - '0' : 0);
					position++; // Also incremented below
				}
			}
			position++;
		}
		else {
			// Should we change the current code?
			// Do we have a code set?
			if (codeSet == 0) {
				// No, we don't have a code set
				if (newCodeSet == CODE_CODE_B) {
					patternIndex = CODE_START_B;
				}
				else {
					// CODE_CODE_C
					patternIndex = CODE_START_C;
				}
			}
			else {
				// Yes, we have a code set
				patternIndex = newCodeSet;
			}
			codeSet = newCodeSet;
		}

		// Get the pattern
		patterns.push_back(Code128::CODE_PATTERNS[patternIndex]);

		// Compute checksum
		checkSum += patternIndex * checkWeight;
		if (position != 0) {
			checkWeight++;
		}
	}

	// Compute and append checksum
	checkSum %= 103;
	patterns.push_back(Code128::CODE_PATTERNS[checkSum]);

	// Append stop code
	patterns.push_back(Code128::CODE_PATTERNS[CODE_STOP]);

	// Compute code width
	int codeWidth = 0;
	for (const std::vector<int>& pattern : patterns) {
		codeWidth += std::accumulate(pattern.begin(), pattern.end(), 0);
	}

	// Compute result
	std::vector<bool> result(codeWidth, false);
	int pos = 0;
	for (const std::vector<int>& pattern : patterns) {
		pos += WriterHelper::AppendPattern(result, pos, pattern, true);
	}

	WriterHelper::RenderResult(result, width, height, _sidesMargin >= 0 ? _sidesMargin : 10, output);
}

} // OneD
} // ZXing
<|endoftext|>


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

#include "webkit/plugins/ppapi/ppb_surface_3d_impl.h"

#include "base/message_loop.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "ppapi/c/dev/ppb_graphics_3d_dev.h"
#include "ppapi/c/dev/ppp_graphics_3d_dev.h"
#include "webkit/plugins/ppapi/common.h"
#include "webkit/plugins/ppapi/plugin_module.h"
#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
#include "webkit/plugins/ppapi/ppb_context_3d_impl.h"

namespace webkit {
namespace ppapi {

namespace {

PP_Resource Create(PP_Instance instance_id,
                   PP_Config3D_Dev config,
                   const int32_t* attrib_list) {
  PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
  if (!instance)
    return 0;

  scoped_refptr<PPB_Surface3D_Impl> surface(
      new PPB_Surface3D_Impl(instance));
  if (!surface->Init(config, attrib_list))
    return 0;

  return surface->GetReference();
}

PP_Bool IsSurface3D(PP_Resource resource) {
  return BoolToPPBool(!!Resource::GetAs<PPB_Surface3D_Impl>(resource));
}

int32_t SetAttrib(PP_Resource surface_id,
                  int32_t attribute,
                  int32_t value) {
  // TODO(alokp): Implement me.
  return 0;
}

int32_t GetAttrib(PP_Resource surface_id,
                  int32_t attribute,
                  int32_t* value) {
  // TODO(alokp): Implement me.
  return 0;
}

int32_t SwapBuffers(PP_Resource surface_id,
                    PP_CompletionCallback callback) {
  scoped_refptr<PPB_Surface3D_Impl> surface(
      Resource::GetAs<PPB_Surface3D_Impl>(surface_id));
  return surface->SwapBuffers(callback);
}

const PPB_Surface3D_Dev ppb_surface3d = {
  &Create,
  &IsSurface3D,
  &SetAttrib,
  &GetAttrib,
  &SwapBuffers
};

}  // namespace

PPB_Surface3D_Impl::PPB_Surface3D_Impl(PluginInstance* instance)
    : Resource(instance),
      bound_to_instance_(false),
      swap_initiated_(false),
      swap_callback_(PP_BlockUntilComplete()),
      context_(NULL) {
}

PPB_Surface3D_Impl::~PPB_Surface3D_Impl() {
}

const PPB_Surface3D_Dev* PPB_Surface3D_Impl::GetInterface() {
  return &ppb_surface3d;
}

PPB_Surface3D_Impl* PPB_Surface3D_Impl::AsPPB_Surface3D_Impl() {
  return this;
}

bool PPB_Surface3D_Impl::Init(PP_Config3D_Dev config,
                              const int32_t* attrib_list) {
  return true;
}

bool PPB_Surface3D_Impl::BindToInstance(bool bind) {
  bound_to_instance_ = bind;
  return true;
}

bool PPB_Surface3D_Impl::BindToContext(
    PPB_Context3D_Impl* context) {
  if (context == context_)
    return true;

  // Unbind from the current context.
  if (context_) {
    context_->platform_context()->SetSwapBuffersCallback(NULL);
  }
  if (context) {
    // Resize the backing texture to the size of the instance when it is bound.
    // TODO(alokp): This should be the responsibility of plugins.
    gpu::gles2::GLES2Implementation* impl = context->gles2_impl();
    if (impl) {
      const gfx::Size& size = instance()->position().size();
      impl->ResizeCHROMIUM(size.width(), size.height());
    }

    context->platform_context()->SetSwapBuffersCallback(
        NewCallback(this, &PPB_Surface3D_Impl::OnSwapBuffers));
  }
  context_ = context;
  return true;
}

int32_t PPB_Surface3D_Impl::SwapBuffers(PP_CompletionCallback callback) {
  if (!context_)
    return PP_ERROR_FAILED;

  if (swap_callback_.func) {
    // Already a pending SwapBuffers that hasn't returned yet.
    return PP_ERROR_INPROGRESS;
  }

  if (!callback.func) {
    // Blocking SwapBuffers isn't supported (since we have to be on the main
    // thread).
    return PP_ERROR_BADARGUMENT;
  }

  swap_callback_ = callback;
  gpu::gles2::GLES2Implementation* impl = context_->gles2_impl();
  if (impl) {
    context_->gles2_impl()->SwapBuffers();
  }
  return PP_ERROR_WOULDBLOCK;
}

void PPB_Surface3D_Impl::ViewInitiatedPaint() {
}

void PPB_Surface3D_Impl::ViewFlushedPaint() {
  if (swap_initiated_ && swap_callback_.func) {
    // We must clear swap_callback_ before issuing the callback. It will be
    // common for the plugin to issue another SwapBuffers in response to the
    // callback, and we don't want to think that a callback is already pending.
    PP_CompletionCallback callback = PP_BlockUntilComplete();
    std::swap(callback, swap_callback_);
    swap_initiated_ = false;
    PP_RunCompletionCallback(&callback, PP_OK);
  }
}

unsigned int PPB_Surface3D_Impl::GetBackingTextureId() {
  return context_ ? context_->platform_context()->GetBackingTextureId() : 0;
}

void PPB_Surface3D_Impl::OnSwapBuffers() {
  if (bound_to_instance_) {
    instance()->CommitBackingTexture();
    swap_initiated_ = true;
  } else if (swap_callback_.func) {
    // If we're off-screen, no need to trigger compositing so run the callback
    // immediately.
    PP_CompletionCallback callback = PP_BlockUntilComplete();
    std::swap(callback, swap_callback_);
    swap_initiated_ = false;
    PP_RunCompletionCallback(&callback, PP_OK);
  }
}

void PPB_Surface3D_Impl::OnContextLost() {
  if (bound_to_instance_)
    instance()->BindGraphics(0);

  // Send context lost to plugin. This may have been caused by a PPAPI call, so
  // avoid re-entering.
  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
      this, &PPB_Surface3D_Impl::SendContextLost));
}

void PPB_Surface3D_Impl::SendContextLost() {
  const PPP_Graphics3D_Dev* ppp_graphics_3d =
      static_cast<const PPP_Graphics3D_Dev*>(
          instance()->module()->GetPluginInterface(
              PPP_GRAPHICS_3D_DEV_INTERFACE));
  if (ppp_graphics_3d)
    ppp_graphics_3d->Graphics3DContextLost(instance()->pp_instance());
}

}  // namespace ppapi
}  // namespace webkit

<commit_msg>Fix write-after-free in PPB_Surface_3D_Impl<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/plugins/ppapi/ppb_surface_3d_impl.h"

#include "base/message_loop.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "ppapi/c/dev/ppb_graphics_3d_dev.h"
#include "ppapi/c/dev/ppp_graphics_3d_dev.h"
#include "webkit/plugins/ppapi/common.h"
#include "webkit/plugins/ppapi/plugin_module.h"
#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
#include "webkit/plugins/ppapi/ppb_context_3d_impl.h"

namespace webkit {
namespace ppapi {

namespace {

PP_Resource Create(PP_Instance instance_id,
                   PP_Config3D_Dev config,
                   const int32_t* attrib_list) {
  PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
  if (!instance)
    return 0;

  scoped_refptr<PPB_Surface3D_Impl> surface(
      new PPB_Surface3D_Impl(instance));
  if (!surface->Init(config, attrib_list))
    return 0;

  return surface->GetReference();
}

PP_Bool IsSurface3D(PP_Resource resource) {
  return BoolToPPBool(!!Resource::GetAs<PPB_Surface3D_Impl>(resource));
}

int32_t SetAttrib(PP_Resource surface_id,
                  int32_t attribute,
                  int32_t value) {
  // TODO(alokp): Implement me.
  return 0;
}

int32_t GetAttrib(PP_Resource surface_id,
                  int32_t attribute,
                  int32_t* value) {
  // TODO(alokp): Implement me.
  return 0;
}

int32_t SwapBuffers(PP_Resource surface_id,
                    PP_CompletionCallback callback) {
  scoped_refptr<PPB_Surface3D_Impl> surface(
      Resource::GetAs<PPB_Surface3D_Impl>(surface_id));
  return surface->SwapBuffers(callback);
}

const PPB_Surface3D_Dev ppb_surface3d = {
  &Create,
  &IsSurface3D,
  &SetAttrib,
  &GetAttrib,
  &SwapBuffers
};

}  // namespace

PPB_Surface3D_Impl::PPB_Surface3D_Impl(PluginInstance* instance)
    : Resource(instance),
      bound_to_instance_(false),
      swap_initiated_(false),
      swap_callback_(PP_BlockUntilComplete()),
      context_(NULL) {
}

PPB_Surface3D_Impl::~PPB_Surface3D_Impl() {
  if (context_)
    context_->BindSurfaces(NULL, NULL);
}

const PPB_Surface3D_Dev* PPB_Surface3D_Impl::GetInterface() {
  return &ppb_surface3d;
}

PPB_Surface3D_Impl* PPB_Surface3D_Impl::AsPPB_Surface3D_Impl() {
  return this;
}

bool PPB_Surface3D_Impl::Init(PP_Config3D_Dev config,
                              const int32_t* attrib_list) {
  return true;
}

bool PPB_Surface3D_Impl::BindToInstance(bool bind) {
  bound_to_instance_ = bind;
  return true;
}

bool PPB_Surface3D_Impl::BindToContext(
    PPB_Context3D_Impl* context) {
  if (context == context_)
    return true;

  // Unbind from the current context.
  if (context_) {
    context_->platform_context()->SetSwapBuffersCallback(NULL);
  }
  if (context) {
    // Resize the backing texture to the size of the instance when it is bound.
    // TODO(alokp): This should be the responsibility of plugins.
    gpu::gles2::GLES2Implementation* impl = context->gles2_impl();
    if (impl) {
      const gfx::Size& size = instance()->position().size();
      impl->ResizeCHROMIUM(size.width(), size.height());
    }

    context->platform_context()->SetSwapBuffersCallback(
        NewCallback(this, &PPB_Surface3D_Impl::OnSwapBuffers));
  }
  context_ = context;
  return true;
}

int32_t PPB_Surface3D_Impl::SwapBuffers(PP_CompletionCallback callback) {
  if (!context_)
    return PP_ERROR_FAILED;

  if (swap_callback_.func) {
    // Already a pending SwapBuffers that hasn't returned yet.
    return PP_ERROR_INPROGRESS;
  }

  if (!callback.func) {
    // Blocking SwapBuffers isn't supported (since we have to be on the main
    // thread).
    return PP_ERROR_BADARGUMENT;
  }

  swap_callback_ = callback;
  gpu::gles2::GLES2Implementation* impl = context_->gles2_impl();
  if (impl) {
    context_->gles2_impl()->SwapBuffers();
  }
  return PP_ERROR_WOULDBLOCK;
}

void PPB_Surface3D_Impl::ViewInitiatedPaint() {
}

void PPB_Surface3D_Impl::ViewFlushedPaint() {
  if (swap_initiated_ && swap_callback_.func) {
    // We must clear swap_callback_ before issuing the callback. It will be
    // common for the plugin to issue another SwapBuffers in response to the
    // callback, and we don't want to think that a callback is already pending.
    PP_CompletionCallback callback = PP_BlockUntilComplete();
    std::swap(callback, swap_callback_);
    swap_initiated_ = false;
    PP_RunCompletionCallback(&callback, PP_OK);
  }
}

unsigned int PPB_Surface3D_Impl::GetBackingTextureId() {
  return context_ ? context_->platform_context()->GetBackingTextureId() : 0;
}

void PPB_Surface3D_Impl::OnSwapBuffers() {
  if (bound_to_instance_) {
    instance()->CommitBackingTexture();
    swap_initiated_ = true;
  } else if (swap_callback_.func) {
    // If we're off-screen, no need to trigger compositing so run the callback
    // immediately.
    PP_CompletionCallback callback = PP_BlockUntilComplete();
    std::swap(callback, swap_callback_);
    swap_initiated_ = false;
    PP_RunCompletionCallback(&callback, PP_OK);
  }
}

void PPB_Surface3D_Impl::OnContextLost() {
  if (bound_to_instance_)
    instance()->BindGraphics(0);

  // Send context lost to plugin. This may have been caused by a PPAPI call, so
  // avoid re-entering.
  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
      this, &PPB_Surface3D_Impl::SendContextLost));
}

void PPB_Surface3D_Impl::SendContextLost() {
  const PPP_Graphics3D_Dev* ppp_graphics_3d =
      static_cast<const PPP_Graphics3D_Dev*>(
          instance()->module()->GetPluginInterface(
              PPP_GRAPHICS_3D_DEV_INTERFACE));
  if (ppp_graphics_3d)
    ppp_graphics_3d->Graphics3DContextLost(instance()->pp_instance());
}

}  // namespace ppapi
}  // namespace webkit

<|endoftext|>


<commit_before>#include "OccBody.hpp"
#include "OccBody_impl.hpp"
#include "OccUtils.hpp"

#include <boost/math/quaternion.hpp>

OccBody::OccBody(SP::SiconosVector position,
                 SP::SiconosVector velocity,
                 double mass ,
                 SP::SiconosMatrix inertia) :
  NewtonEulerDS(position, velocity, mass, inertia),
  _contactShapes(new ContactShapes()),
  _shapes(new TopoDS_Shapes())
{}

void OccBody::addContactShape(SP::OccContactShape shape,
                              SP::SiconosVector pos,
                              SP::SiconosVector ori,
                              unsigned int group)
{
  OffSet offset = { {(*pos)(0), (*pos)(1), (*pos)(2),
                     (*ori)(0), (*ori)(1), (*ori)(2), (*ori)(3)}};

  this->_contactShapes->push_back(
    boost::tuple<SP::OccContactShape, OffSet, int>(shape, offset, group));

  this->updateContactShapes();
  shape->computeUVBounds();
}

void OccBody::addShape(SP::TopoDS_Shape shape,
                       SP::SiconosVector pos,
                       SP::SiconosVector ori)
{

  OffSet offset = { {(*pos)(0), (*pos)(1), (*pos)(2),
                     (*ori)(0), (*ori)(1), (*ori)(2), (*ori)(3)}};

  this->_shapes->push_back(
    boost::tuple<SP::TopoDS_Shape, OffSet>(shape, offset));

  this->updateShapes();
}

void OccBody::updateContactShapes()
{
  boost::math::quaternion<double> q((*_q)(3), (*_q)(4), (*_q)(5), (*_q)(6));

  for (ContactShapes::iterator csi = _contactShapes->begin();
       csi != _contactShapes->end(); ++ csi)
  {
    OffSet offset = boost::get<1>(*csi);

    boost::math::quaternion<double> pv = boost::math::quaternion<double>(0, offset[0], offset[1], offset[2]);

    boost::math::quaternion<double> rv = q * pv * boost::math::conj(q);

    boost::math::quaternion<double> r = q * boost::math::quaternion<double>(offset[3], offset[4], offset[5], offset[6]);

    SiconosVector fp = SiconosVector(7);
    fp(0) = (*_q)(0)+rv.R_component_2();
    fp(1) = (*_q)(1)+rv.R_component_3();
    fp(2) = (*_q)(2)+rv.R_component_4();
    fp(3) = r.R_component_1();
    fp(4) = r.R_component_2();
    fp(5) = r.R_component_3();
    fp(6) = r.R_component_4();

    occ_move(boost::get<0>(*csi)->data(), fp);
  }
}

void OccBody::updateShapes()
{

   boost::math::quaternion<double> q((*_q)(3), (*_q)(4), (*_q)(5), (*_q)(6));

  for (TopoDS_Shapes::iterator csi = _shapes->begin();
       csi != _shapes->end(); ++ csi)
  {

    OffSet offset = boost::get<1>(*csi);

    boost::math::quaternion<double> pv = boost::math::quaternion<double>(0, offset[0], offset[1], offset[2]);

    boost::math::quaternion<double> rv = q * pv * boost::math::conj(q);

    boost::math::quaternion<double> r = q * boost::math::quaternion<double>(offset[3], offset[4], offset[5], offset[6]);

    SiconosVector fp = SiconosVector(7);
    fp(0) = (*_q)(0)+rv.R_component_2();
    fp(1) = (*_q)(1)+rv.R_component_3();
    fp(2) = (*_q)(2)+rv.R_component_4();
    fp(3) = r.R_component_1();
    fp(4) = r.R_component_2();
    fp(5) = r.R_component_3();
    fp(6) = r.R_component_4();

    occ_move(*(boost::get<0>(*csi)), fp);
  }
}

const OccContactShape& OccBody::contactShape(unsigned int id) const
{
  return *boost::get<0>((*this->_contactShapes)[id]);
}

const TopoDS_Shape& OccBody::shape(unsigned int id) const
{
  return *boost::get<0>((*this->_shapes)[id]);
}
<commit_msg>[mechanics occ] fix testOcc for when no offset specified to OccBody<commit_after>#include "OccBody.hpp"
#include "OccBody_impl.hpp"
#include "OccUtils.hpp"

#include <boost/math/quaternion.hpp>

OccBody::OccBody(SP::SiconosVector position,
                 SP::SiconosVector velocity,
                 double mass ,
                 SP::SiconosMatrix inertia) :
  NewtonEulerDS(position, velocity, mass, inertia),
  _contactShapes(new ContactShapes()),
  _shapes(new TopoDS_Shapes())
{}

void OccBody::addContactShape(SP::OccContactShape shape,
                              SP::SiconosVector pos,
                              SP::SiconosVector ori,
                              unsigned int group)
{
  OffSet offset = {0, 0, 0, 1, 0, 0 ,0};
  if (pos) {
    offset[0] = (*pos)(0);
    offset[1] = (*pos)(1);
    offset[2] = (*pos)(2);
  }
  if (ori) {
    offset[3] = (*ori)(0);
    offset[4] = (*ori)(1);
    offset[5] = (*ori)(2);
    offset[6] = (*ori)(3);
  }

  this->_contactShapes->push_back(
    boost::tuple<SP::OccContactShape, OffSet, int>(shape, offset, group));

  this->updateContactShapes();
  shape->computeUVBounds();
}

void OccBody::addShape(SP::TopoDS_Shape shape,
                       SP::SiconosVector pos,
                       SP::SiconosVector ori)
{
  OffSet offset = {0, 0, 0, 1, 0, 0 ,0};
  if (pos) {
    offset[0] = (*pos)(0);
    offset[1] = (*pos)(1);
    offset[2] = (*pos)(2);
  }
  if (ori) {
    offset[3] = (*ori)(0);
    offset[4] = (*ori)(1);
    offset[5] = (*ori)(2);
    offset[6] = (*ori)(3);
  }

  this->_shapes->push_back(
    boost::tuple<SP::TopoDS_Shape, OffSet>(shape, offset));

  this->updateShapes();
}

void OccBody::updateContactShapes()
{
  boost::math::quaternion<double> q((*_q)(3), (*_q)(4), (*_q)(5), (*_q)(6));

  for (ContactShapes::iterator csi = _contactShapes->begin();
       csi != _contactShapes->end(); ++ csi)
  {
    OffSet offset = boost::get<1>(*csi);

    boost::math::quaternion<double> pv = boost::math::quaternion<double>(0, offset[0], offset[1], offset[2]);

    boost::math::quaternion<double> rv = q * pv * boost::math::conj(q);

    boost::math::quaternion<double> r = q * boost::math::quaternion<double>(offset[3], offset[4], offset[5], offset[6]);

    SiconosVector fp = SiconosVector(7);
    fp(0) = (*_q)(0)+rv.R_component_2();
    fp(1) = (*_q)(1)+rv.R_component_3();
    fp(2) = (*_q)(2)+rv.R_component_4();
    fp(3) = r.R_component_1();
    fp(4) = r.R_component_2();
    fp(5) = r.R_component_3();
    fp(6) = r.R_component_4();

    occ_move(boost::get<0>(*csi)->data(), fp);
  }
}

void OccBody::updateShapes()
{

   boost::math::quaternion<double> q((*_q)(3), (*_q)(4), (*_q)(5), (*_q)(6));

  for (TopoDS_Shapes::iterator csi = _shapes->begin();
       csi != _shapes->end(); ++ csi)
  {

    OffSet offset = boost::get<1>(*csi);

    boost::math::quaternion<double> pv = boost::math::quaternion<double>(0, offset[0], offset[1], offset[2]);

    boost::math::quaternion<double> rv = q * pv * boost::math::conj(q);

    boost::math::quaternion<double> r = q * boost::math::quaternion<double>(offset[3], offset[4], offset[5], offset[6]);

    SiconosVector fp = SiconosVector(7);
    fp(0) = (*_q)(0)+rv.R_component_2();
    fp(1) = (*_q)(1)+rv.R_component_3();
    fp(2) = (*_q)(2)+rv.R_component_4();
    fp(3) = r.R_component_1();
    fp(4) = r.R_component_2();
    fp(5) = r.R_component_3();
    fp(6) = r.R_component_4();

    occ_move(*(boost::get<0>(*csi)), fp);
  }
}

const OccContactShape& OccBody::contactShape(unsigned int id) const
{
  return *boost::get<0>((*this->_contactShapes)[id]);
}

const TopoDS_Shape& OccBody::shape(unsigned int id) const
{
  return *boost::get<0>((*this->_shapes)[id]);
}
<|endoftext|>