text:
// 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.
//
// The following only applies to changes made to this file as part of YugaByte development.
//
// Portions Copyright (c) YugaByte, Inc.
//
// 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 "yb/client/batcher.h"

#include <algorithm>
#include <memory>
#include <mutex>
#include <set>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include <boost/optional/optional_io.hpp>
#include <glog/logging.h>

#include "yb/client/async_rpc.h"
#include "yb/client/callbacks.h"
#include "yb/client/client.h"
#include "yb/client/client-internal.h"
#include "yb/client/client_error.h"
#include "yb/client/error_collector.h"
#include "yb/client/error.h"
#include "yb/client/in_flight_op.h"
#include "yb/client/meta_cache.h"
#include "yb/client/rejection_score_source.h"
#include "yb/client/session.h"
#include "yb/client/table.h"
#include "yb/client/transaction.h"
#include "yb/client/yb_op.h"

#include "yb/common/wire_protocol.h"
#include "yb/gutil/strings/human_readable.h"
#include "yb/gutil/strings/join.h"

#include "yb/util/debug-util.h"
#include "yb/util/flag_tags.h"
#include "yb/util/logging.h"

// When this flag is set to false and we have separate errors for operation, then batcher would
// report IO Error status. Otherwise we will try to combine errors from separate operation to
// status of batch. Useful in tests, when we don't need complex error analysis.
DEFINE_test_flag(bool, combine_batcher_errors, false,
                 "Whether combine errors into batcher status.");
DEFINE_test_flag(double, simulate_tablet_lookup_does_not_match_partition_key_probability, 0.0,
                 "Probability for simulating the error that happens when a key is not in the key "
                 "range of the resolved tablet's partition.");

using std::pair;
using std::set;
using std::unique_ptr;
using std::shared_ptr;
using std::unordered_map;
using strings::Substitute;

using namespace std::placeholders;

namespace yb {

using tserver::WriteResponsePB;
using tserver::WriteResponsePB_PerRowErrorPB;

namespace client {

namespace internal {

// TODO: instead of using a string error message, make Batcher return a status other than IOError.
// (https://github.com/YugaByte/yugabyte-db/issues/702)
const std::string Batcher::kErrorReachingOutToTServersMsg(
    "Errors occurred while reaching out to the tablet servers");

// About lock ordering in this file:
// ------------------------------
// The locks must be acquired in the following order:
//   - Batcher::lock_
//   - InFlightOp::lock_
//
// It's generally important to release all the locks before either calling
// a user callback, or chaining to another async function, since that function
// may also chain directly to the callback. Without releasing locks first,
// the lock ordering may be violated, or a lock may deadlock on itself (these
// locks are non-reentrant).
// ------------------------------------------------------------

Batcher::Batcher(YBClient* client,
                 const YBSessionPtr& session,
                 YBTransactionPtr transaction,
                 ConsistentReadPoint* read_point,
                 bool force_consistent_read)
  : client_(client),
    weak_session_(session),
    next_op_sequence_number_(0),
    async_rpc_metrics_(session->async_rpc_metrics()),
    transaction_(std::move(transaction)),
    read_point_(read_point),
    force_consistent_read_(force_consistent_read) {
}

void Batcher::Abort(const Status& status) {
  bool run_callback;
  {
    std::lock_guard<decltype(mutex_)> lock(mutex_);
    state_ = BatcherState::kAborted;

    InFlightOps to_abort;
    for (auto& op : ops_) {
      if (op->state.load(std::memory_order_acquire) == InFlightOpState::kBufferedToTabletServer) {
        to_abort.push_back(op);
      }
    }

    for (auto& op : to_abort) {
      VLOG_WITH_PREFIX(1) << "Aborting op: " << op->ToString();
      MarkInFlightOpFailedUnlocked(op, status);
    }

    run_callback = flush_callback_;
  }

  if (run_callback) {
    RunCallback(status);
  }
}

Batcher::~Batcher() {
  if (PREDICT_FALSE(!ops_.empty())) {
    for (auto& op : ops_) {
      LOG_WITH_PREFIX(ERROR) << "Orphaned op: " << op->ToString();
    }
    if (state_ != BatcherState::kAddFailed) {
      // OK to destruct batcher failed due error calling Add() even with ops_ not empty.
      LOG_WITH_PREFIX(FATAL) << "ops_ not empty";
    }
  }
  CHECK(
      state_ == BatcherState::kComplete || state_ == BatcherState::kAborted ||
      state_ == BatcherState::kAddFailed)
      << "Bad state: " << state_;
}

void Batcher::SetDeadline(CoarseTimePoint deadline) {
  std::lock_guard<decltype(mutex_)> lock(mutex_);
  deadline_ = deadline;
}

bool Batcher::HasPendingOperations() const {
  std::lock_guard<decltype(mutex_)> lock(mutex_);
  return !ops_.empty();
}

int Batcher::CountBufferedOperations() const {
  std::lock_guard<decltype(mutex_)> lock(mutex_);
  if (state_ == BatcherState::kGatheringOps) {
    return ops_.size();
  } else {
    // If we've already started to flush, then the ops aren't
    // considered "buffered".
    return 0;
  }
}

int Batcher::GetAddedNotFlushedOperationsCount() const {
  std::lock_guard<decltype(mutex_)> lock(mutex_);
  return added_not_flushed_operations_count_;
}

void Batcher::CheckForFinishedFlush() {
  YBSessionPtr session;
  {
    std::lock_guard<decltype(mutex_)> lock(mutex_);
    if (!ops_.empty()) {
      // Did not finish yet.
      return;
    }

    // Possible cases when we should ignore this check:
    // kComplete - because of race condition CheckForFinishedFlush could be invoked from 2 threads
    //             and one of them just finished last operation.
    // kGatheringOps - lookup failure happened while batcher is getting filled with operations.
    // kAborted - batcher has been aborted (including internally due to tablet lookup failure).
    if (state_ == BatcherState::kComplete || state_ == BatcherState::kGatheringOps ||
        state_ == BatcherState::kAborted) {
      return;
    }

    if (state_ != BatcherState::kResolvingTablets &&
        state_ != BatcherState::kTransactionReady) {
      LOG_WITH_PREFIX(DFATAL) << "Batcher finished in a wrong state: " << AsString(state_) << "\n"
                              << GetStackTrace();
      return;
    }

    session = weak_session_.lock();
    state_ = BatcherState::kComplete;
  }

  if (session) {
    // Important to do this outside of the lock so that we don't have
    // a lock inversion deadlock -- the session lock should always
    // come before the batcher lock.
    session->FlushFinished(this);
  }

  Status s;
  if (!combined_error_.ok()) {
    s = combined_error_;
  } else if (had_errors_.load(std::memory_order_acquire)) {
    // In the general case, the user is responsible for fetching errors from the error collector.
    // TODO: use the Combined status here, so it is easy to recognize.
    // https://github.com/YugaByte/yugabyte-db/issues/702
    s = STATUS(IOError, kErrorReachingOutToTServersMsg);
  }

  RunCallback(s);
}

void Batcher::RunCallback(const Status& status) {
  auto runnable = std::make_shared<yb::FunctionRunnable>(
      [ cb{std::move(flush_callback_)}, status ]() { cb(status); });
  if (!client_->callback_threadpool() || !client_->callback_threadpool()->Submit(runnable).ok()) {
    runnable->Run();
  }
}

void Batcher::FlushAsync(
    StatusFunctor callback, const IsWithinTransactionRetry is_within_transaction_retry) {
  YBSessionPtr session;
  size_t operations_count;
  {
    std::lock_guard<decltype(mutex_)> lock(mutex_);
    if (state_ == BatcherState::kAddFailed) {
      callback(STATUS(IllegalState, "Batcher failed due to error in add call"));
      return;
    }
    CHECK_EQ(state_, BatcherState::kGatheringOps);
    state_ = BatcherState::kResolvingTablets;
    flush_callback_ = std::move(callback);
    operations_count = added_not_flushed_operations_count_;
    added_not_flushed_operations_count_ = 0;
    session = weak_session_.lock();
  }
  if (session) {
    // Important to do this outside of the lock so that we don't have
    // a lock inversion deadlock -- the session lock should always
    // come before the batcher lock.
    session->FlushStarted(this);
  }

  auto transaction = this->transaction();
  // If YBSession retries previously failed ops within the same transaction, these ops are already
  // expected by transaction.
  if (transaction && !is_within_transaction_retry) {
    transaction->ExpectOperations(operations_count);
  }

  // In the case that we have nothing buffered, just call the callback
  // immediately. Otherwise, the callback will be called by the last callback
  // when it sees that the ops_ list has drained.
  CheckForFinishedFlush();

  // Trigger flushing of all of the buffers. Some of these may already have
  // been flushed through an async path, but it's idempotent - a second call
  // to flush would just be a no-op.
  //
  // If some of the operations are still in-flight, then they'll get sent
  // when they hit 'per_tablet_ops', since our state is now kResolvingTablets.
  FlushBuffersIfReady();
}

Status Batcher::Add(shared_ptr<YBOperation> yb_op) {
  auto s = DoAdd(std::move(yb_op));
  if (!s.ok()) {
    std::lock_guard<decltype(mutex_)> lock(mutex_);
    state_ = BatcherState::kAddFailed;
  }
  return s;
}

Status Batcher::DoAdd(shared_ptr<YBOperation> yb_op) {
  if (state() != BatcherState::kGatheringOps) {
    const auto error =
        STATUS_FORMAT(InternalError, "Adding op to batcher in a wrong state: $0", state_);
    LOG(DFATAL) << error << "\n" << GetStackTrace();
    return error;
  }
  // As soon as we get the op, start looking up where it belongs,
  // so that when the user calls Flush, we are ready to go.
  auto in_flight_op = std::make_shared<InFlightOp>(yb_op);
  RETURN_NOT_OK(yb_op->GetPartitionKey(&in_flight_op->partition_key));

  // TODO(tsplit): Consider implementing Batcher::AddInflightOp that returns void and use it for
  // retries.
  // TODO(tsplit): Consider doing refresh somewhere else, not inside Batcher::Add.
  if (VERIFY_RESULT(yb_op->MaybeRefreshTablePartitionList())) {
    client_->data_->meta_cache_->InvalidateTableCache(*yb_op->table());
  }

  if (yb_op->table()->partition_schema().IsHashPartitioning()) {
    switch (yb_op->type()) {
      case YBOperation::Type::QL_READ:
        if (!in_flight_op->partition_key.empty()) {
          down_cast<YBqlOp *>(yb_op.get())->SetHashCode(
              PartitionSchema::DecodeMultiColumnHashValue(in_flight_op->partition_key));
        }
        break;
      case YBOperation::Type::QL_WRITE:
        down_cast<YBqlOp*>(yb_op.get())->SetHashCode(
            PartitionSchema::DecodeMultiColumnHashValue(in_flight_op->partition_key));
        break;
      case YBOperation::Type::REDIS_READ:
        down_cast<YBRedisReadOp*>(yb_op.get())->SetHashCode(
            PartitionSchema::DecodeMultiColumnHashValue(in_flight_op->partition_key));
        break;
      case YBOperation::Type::REDIS_WRITE:
        down_cast<YBRedisWriteOp*>(yb_op.get())->SetHashCode(
            PartitionSchema::DecodeMultiColumnHashValue(in_flight_op->partition_key));
        break;
      case YBOperation::Type::PGSQL_READ:
        if (!in_flight_op->partition_key.empty()) {
          down_cast<YBPgsqlReadOp *>(yb_op.get())->SetHashCode(
              PartitionSchema::DecodeMultiColumnHashValue(in_flight_op->partition_key));
        }
        break;
      case YBOperation::Type::PGSQL_WRITE:
        down_cast<YBPgsqlWriteOp*>(yb_op.get())->SetHashCode(
            PartitionSchema::DecodeMultiColumnHashValue(in_flight_op->partition_key));
        break;
    }
  }

  AddInFlightOp(in_flight_op);
  VLOG_WITH_PREFIX(3) << "Looking up tablet for " << in_flight_op->yb_op->ToString()
                      << " partition key: "
                      << Slice(in_flight_op->partition_key).ToDebugHexString();

  if (yb_op->tablet()) {
    TabletLookupFinished(std::move(in_flight_op), yb_op->tablet());
  } else {
    client_->data_->meta_cache_->LookupTabletByKey(
        in_flight_op->yb_op->table(), in_flight_op->partition_key, deadline_,
        std::bind(&Batcher::TabletLookupFinished, BatcherPtr(this), in_flight_op, _1));
  }
  return Status::OK();
}

void Batcher::AddInFlightOp(const InFlightOpPtr& op) {
  LOG_IF(DFATAL, op->state != InFlightOpState::kLookingUpTablet)
      << "Adding in flight op in a wrong state: " << op->state;

  std::lock_guard<decltype(mutex_)> lock(mutex_);
  CHECK_EQ(state_, BatcherState::kGatheringOps);
  CHECK(ops_.insert(op).second);
  op->sequence_number_ = next_op_sequence_number_++;
  ++outstanding_lookups_;
  ++added_not_flushed_operations_count_;
}

bool Batcher::IsAbortedUnlocked() const {
  return state_ == BatcherState::kAborted;
}

void Batcher::CombineErrorUnlocked(const InFlightOpPtr& in_flight_op, const Status& status) {
  error_collector_.AddError(in_flight_op->yb_op, status);
  if (FLAGS_TEST_combine_batcher_errors) {
    if (combined_error_.ok()) {
      combined_error_ = status.CloneAndPrepend(in_flight_op->ToString());
    } else if (!combined_error_.IsCombined() && combined_error_.code() != status.code()) {
      combined_error_ = STATUS(Combined, "Multiple failures");
    }
  }
  had_errors_.store(true, std::memory_order_release);
}

void Batcher::MarkInFlightOpFailedUnlocked(const InFlightOpPtr& in_flight_op, const Status& s) {
  CHECK_EQ(1, ops_.erase(in_flight_op)) << "Could not remove op " << in_flight_op->ToString()
                                        << " from in-flight list";
  if (ClientError(s) == ClientErrorCode::kTablePartitionListIsStale) {
    // MetaCache returns ClientErrorCode::kTablePartitionListIsStale error for tablet lookup request
    // in case GetTabletLocations from master returns newer version of table partitions.
    // Since MetaCache has no write access to YBTable, it just returns an error which we receive
    // here and mark the table partitions as stale, so they will be refetched on retry.
    // TODO(tsplit): handle splitting-related retries on YB level instead of returning back to
    // client app/driver.
    in_flight_op->yb_op->MarkTablePartitionListAsStale();
  }
  CombineErrorUnlocked(in_flight_op, s);
}

void Batcher::TabletLookupFinished(
    InFlightOpPtr op, Result<internal::RemoteTabletPtr> lookup_result) {
  // Acquire the batcher lock early to atomically:
  // 1. Test if the batcher was aborted, and
  // 2. Change the op state.

  bool all_lookups_finished;
  {
    std::lock_guard<decltype(mutex_)> lock(mutex_);

    --outstanding_lookups_;
    all_lookups_finished = outstanding_lookups_ == 0;

    if (IsAbortedUnlocked()) {
      VLOG_WITH_PREFIX(1) << "Aborted batch: TabletLookupFinished for " << op->yb_op->ToString();
      MarkInFlightOpFailedUnlocked(op, STATUS(Aborted, "Batch aborted"));
      // 'op' is deleted by above function.
      return;
    }

    if (state_ != BatcherState::kResolvingTablets && state_ != BatcherState::kGatheringOps) {
      LOG_WITH_PREFIX(DFATAL) << "Lookup finished in wrong state: " << ToString(state_);
      return;
    }

    if (lookup_result.ok()) {
      const auto& tablet = *lookup_result;

      const Partition& partition = tablet->partition();

      bool partition_contains_row = false;
      const auto& partition_key = op->partition_key;
      switch (op->yb_op->type()) {
        case YBOperation::QL_READ: FALLTHROUGH_INTENDED;
        case YBOperation::QL_WRITE: FALLTHROUGH_INTENDED;
        case YBOperation::PGSQL_READ: FALLTHROUGH_INTENDED;
        case YBOperation::PGSQL_WRITE: FALLTHROUGH_INTENDED;
        case YBOperation::REDIS_READ: FALLTHROUGH_INTENDED;
        case YBOperation::REDIS_WRITE: {
          partition_contains_row = partition.ContainsKey(partition_key);
          break;
        }
      }

      if (!partition_contains_row ||
          (PREDICT_FALSE(
              RandomActWithProbability(
                  FLAGS_TEST_simulate_tablet_lookup_does_not_match_partition_key_probability) &&
              op->yb_op->table()->name().namespace_name() == "yb_test"))) {
        const Schema& schema = GetSchema(op->yb_op->table()->schema());
        const PartitionSchema& partition_schema = op->yb_op->table()->partition_schema();
        const auto msg = Format(
            "Row $0 not in partition $1, partition key: $2",
            op->yb_op->ToString(),
            partition_schema.PartitionDebugString(partition, schema),
            Slice(partition_key).ToDebugHexString());
        LOG_WITH_PREFIX(DFATAL) << msg;
        lookup_result = STATUS(InternalError, msg);
      } else {
        op->tablet = tablet;
      }
    }

    VLOG_WITH_PREFIX(3) << "TabletLookupFinished for " << op->yb_op->ToString() << ": "
                        << lookup_result << ", outstanding lookups: " << outstanding_lookups_;

    if (lookup_result.ok()) {
      CHECK(*lookup_result);

      auto expected_state = InFlightOpState::kLookingUpTablet;
      if (op->state.compare_exchange_strong(
          expected_state, InFlightOpState::kBufferedToTabletServer, std::memory_order_acq_rel)) {
        ops_queue_.push_back(op);
      } else {
        LOG_WITH_PREFIX(DFATAL) << "Finished lookup for operation in a bad state: "
                                << ToString(expected_state);
      }
    } else {
      MarkInFlightOpFailedUnlocked(op, lookup_result.status());
    }
  }

  if (!lookup_result.ok()) {
    CheckForFinishedFlush();
  }

  if (all_lookups_finished) {
    FlushBuffersIfReady();
  }
}

void Batcher::TransactionReady(const Status& status, const BatcherPtr& self) {
  if (status.ok()) {
    ExecuteOperations(Initial::kFalse);
  } else {
    Abort(status);
  }
}

void Batcher::FlushBuffersIfReady() {
  // We're only ready to flush if both of the following conditions are true:
  // 1. The batcher is in the "resolving tablets" state (i.e. FlushAsync was called).
  // 2. All outstanding ops have finished lookup. Why? To avoid a situation
  //    where ops are flushed one by one as they finish lookup.

  {
    std::lock_guard<decltype(mutex_)> lock(mutex_);
    if (outstanding_lookups_ != 0) {
      // FlushBuffersIfReady is also invoked when all lookups finished, so it ok to just return
      // here.
      VLOG_WITH_PREFIX(3) << "FlushBuffersIfReady: " << outstanding_lookups_
                          << " ops still in lookup";
      return;
    }

    if (state_ != BatcherState::kResolvingTablets) {
      return;
    }

    if (ops_queue_.empty()) {
      // Nothing to prepare.
      state_ = BatcherState::kTransactionReady;
      return;
    }

    state_ = BatcherState::kTransactionPrepare;
  }

  if (had_errors_) {
    // We are doing it to keep guarantee on the order of ops (see InFlightOp::sequence_number_)
    // when we retry on YBSession level.
    // ClientErrorCode::kAbortedBatchDueToFailedTabletLookup is retriable at YBSession level,
    // so YBSession will check other errors in error collector to decide whether to retry.
    static Status tablet_resolution_failed = STATUS(
            Aborted, "Tablet resolution failed for some ops, aborted the whole batch.",
            ClientError(ClientErrorCode::kAbortedBatchDueToFailedTabletLookup));
    Abort(tablet_resolution_failed);
    return;
  }

  // All operations were added, and tablets for them were resolved.
  // So we could sort them.
  std::sort(ops_queue_.begin(),
            ops_queue_.end(),
            [](const InFlightOpPtr& lhs, const InFlightOpPtr& rhs) {
    if (lhs->tablet.get() == rhs->tablet.get()) {
      auto lgroup = lhs->yb_op->group();
      auto rgroup = rhs->yb_op->group();
      if (lgroup != rgroup) {
        return lgroup < rgroup;
      }
      return lhs->sequence_number_ < rhs->sequence_number_;
    }
    return lhs->tablet.get() < rhs->tablet.get();
  });

  auto group_start = ops_queue_.begin();
  auto current_group = (**group_start).yb_op->group();
  const auto* current_tablet = (**group_start).tablet.get();
  for (auto it = group_start; it != ops_queue_.end(); ++it) {
    const auto it_group = (**it).yb_op->group();
    const auto* it_tablet = (**it).tablet.get();
    const auto it_table_partition_list_version = (**it).yb_op->partition_list_version();
    if (it_table_partition_list_version.has_value() &&
        it_table_partition_list_version != it_tablet->partition_list_version()) {
      Abort(STATUS_EC_FORMAT(
          Aborted, ClientError(ClientErrorCode::kTablePartitionListVersionDoesNotMatch),
          "Operation $0 requested table partition list version $1, but ours is: $2",
          (**it).yb_op, it_table_partition_list_version.value(),
          it_tablet->partition_list_version()));
      return;
    }
    if (current_tablet != it_tablet || current_group != it_group) {
      ops_info_.groups.emplace_back(group_start, it);
      group_start = it;
      current_group = it_group;
      current_tablet = it_tablet;
    }
  }
  ops_info_.groups.emplace_back(group_start, ops_queue_.end());

  ExecuteOperations(Initial::kTrue);
}

void Batcher::ExecuteOperations(Initial initial) {
  auto transaction = this->transaction();
  if (transaction) {
    // If this Batcher is executed in context of transaction,
    // then this transaction should initialize metadata used by RPC calls.
    //
    // If transaction is not yet ready to do it, then it will notify as via provided when
    // it could be done.
    if (!transaction->Prepare(&ops_info_,
                              force_consistent_read_,
                              deadline_,
                              initial,
                              std::bind(&Batcher::TransactionReady, this, _1, BatcherPtr(this)))) {
      return;
    }
  }

  {
    std::lock_guard<decltype(mutex_)> lock(mutex_);
    if (state_ != BatcherState::kTransactionPrepare) {
      // Batcher was aborted.
      LOG_IF(DFATAL, state_ != BatcherState::kAborted)
          << "Batcher in a wrong state at the moment the transaction became ready: " << state_;
      return;
    }
    state_ = BatcherState::kTransactionReady;
  }

  // All asynchronous requests were completed, so we could access ops_queue_ w/o holding the lock.
  if (ops_queue_.empty()) {
    return;
  }

  const bool force_consistent_read = force_consistent_read_ || this->transaction();

  const size_t ops_number = ops_queue_.size();

  // Use big enough value for preallocated storage, to avoid unnecessary allocations.
  boost::container::small_vector<std::shared_ptr<AsyncRpc>,
                                 InFlightOpsGroupsWithMetadata::kPreallocatedCapacity> rpcs;
  rpcs.reserve(ops_info_.groups.size());

  // Now flush the ops for each group.
  // Consistent read is not required when whole batch fits into one command.
  const auto need_consistent_read = force_consistent_read || ops_info_.groups.size() > 1;

  for (const auto& group : ops_info_.groups) {
    // Allow local calls for last group only.
    const auto allow_local_calls =
        allow_local_calls_in_curr_thread_ && (&group == &ops_info_.groups.back());
    rpcs.push_back(CreateRpc(
        group.begin->get()->tablet.get(), group, allow_local_calls, need_consistent_read));
  }

  LOG_IF(DFATAL, ops_number != ops_queue_.size())
    << "Ops queue was modified while creating RPCs";
  ops_queue_.clear();

  for (const auto& rpc : rpcs) {
    if (transaction) {
      transaction->trace()->AddChildTrace(rpc->trace());
    }
    rpc->SendRpc();
  }
}

rpc::Messenger* Batcher::messenger() const {
  return client_->messenger();
}

rpc::ProxyCache& Batcher::proxy_cache() const {
  return client_->proxy_cache();
}

YBTransactionPtr Batcher::transaction() const {
  return transaction_;
}

const std::string& Batcher::proxy_uuid() const {
  return client_->proxy_uuid();
}

const ClientId& Batcher::client_id() const {
  return client_->id();
}

std::pair<RetryableRequestId, RetryableRequestId> Batcher::NextRequestIdAndMinRunningRequestId(
    const TabletId& tablet_id) {
  return client_->NextRequestIdAndMinRunningRequestId(tablet_id);
}

void Batcher::RequestFinished(const TabletId& tablet_id, RetryableRequestId request_id) {
  client_->RequestFinished(tablet_id, request_id);
}

std::shared_ptr<AsyncRpc> Batcher::CreateRpc(
    RemoteTablet* tablet, const InFlightOpsGroup& group,
    const bool allow_local_calls_in_curr_thread, const bool need_consistent_read) {
  VLOG_WITH_PREFIX(3) << "FlushBuffersIfReady: already in flushing state, immediately flushing to "
                      << tablet->tablet_id();

  CHECK(group.begin != group.end);

  // Create and send an RPC that aggregates the ops. The RPC is freed when
  // its callback completes.
  //
  // The RPC object takes ownership of the in flight ops.
  // The underlying YB OP is not directly owned, only a reference is kept.

  // Split the read operations according to consistency levels since based on consistency
  // levels the read algorithm would differ.
  const auto op_group = (**group.begin).yb_op->group();
  AsyncRpcData data {
    .batcher = this,
    .tablet = tablet,
    .allow_local_calls_in_curr_thread = allow_local_calls_in_curr_thread,
    .need_consistent_read = need_consistent_read,
    .write_time_for_backfill_ = hybrid_time_for_write_,
    .ops = InFlightOps(group.begin, group.end),
    .need_metadata = group.need_metadata
  };

  switch (op_group) {
    case OpGroup::kWrite:
      return std::make_shared<WriteRpc>(&data);
    case OpGroup::kLeaderRead:
      return std::make_shared<ReadRpc>(&data, YBConsistencyLevel::STRONG);
    case OpGroup::kConsistentPrefixRead:
      return std::make_shared<ReadRpc>(&data, YBConsistencyLevel::CONSISTENT_PREFIX);
  }
  FATAL_INVALID_ENUM_VALUE(OpGroup, op_group);
}

using tserver::ReadResponsePB;

void Batcher::AddOpCountMismatchError() {
  // TODO: how to handle this kind of error where the array of response PB's don't match
  //       the size of the array of requests. We don't have a specific YBOperation to
  //       create an error with, because there are multiple YBOps in one Rpc.
  LOG_WITH_PREFIX(DFATAL) << "Received wrong number of responses compared to request(s) sent.";
}

void Batcher::RemoveInFlightOpsAfterFlushing(
    const InFlightOps& ops, const Status& status, FlushExtraResult flush_extra_result) {
  auto transaction = this->transaction();
  if (transaction) {
    const auto ops_will_be_retried = !status.ok() && ShouldSessionRetryError(status);
    if (!ops_will_be_retried) {
      // We don't call Transaction::Flushed for ops that will be retried within the same
      // transaction in order to keep transaction running until we finally retry all operations
      // successfully or decide to fail and abort the transaction.
      // We also don't call Transaction::Flushed for ops that have been retried, but failed during
      // the retry.
      // See comments for YBTransaction::Impl::running_requests_ and
      // YBSession::AddErrorsAndRunCallback.
      // https://github.com/yugabyte/yugabyte-db/issues/7984.
      transaction->Flushed(ops, flush_extra_result.used_read_time, status);
    }
  }
  if (status.ok() && read_point_) {
    read_point_->UpdateClock(flush_extra_result.propagated_hybrid_time);
  }

  std::lock_guard<decltype(mutex_)> lock(mutex_);
  for (auto& op : ops) {
    CHECK_EQ(1, ops_.erase(op))
      << "Could not remove op " << op->ToString() << " from in-flight list";
  }
}

void Batcher::ProcessRpcStatus(const AsyncRpc &rpc, const Status &s) {
  // TODO: there is a potential race here -- if the Batcher gets destructed while
  // RPCs are in-flight, then accessing state_ will crash. We probably need to keep
  // track of the in-flight RPCs, and in the destructor, change each of them to an
  // "aborted" state.
  std::lock_guard<decltype(mutex_)> lock(mutex_);
  if (state_ != BatcherState::kTransactionReady) {
    LOG_WITH_PREFIX(DFATAL) << "ProcessRpcStatus in wrong state " << ToString(state_) << ": "
                            << rpc.ToString() << ", " << s;
    return;
  }

  if (PREDICT_FALSE(!s.ok())) {
    // Mark each of the ops as failed, since the whole RPC failed.
    for (auto& in_flight_op : rpc.ops()) {
      CombineErrorUnlocked(in_flight_op, s);
    }
  }
}

void Batcher::ProcessReadResponse(const ReadRpc &rpc, const Status &s) {
  ProcessRpcStatus(rpc, s);
}

void Batcher::ProcessWriteResponse(const WriteRpc &rpc, const Status &s) {
  ProcessRpcStatus(rpc, s);

  if (s.ok() && rpc.resp().has_propagated_hybrid_time()) {
    client_->data_->UpdateLatestObservedHybridTime(rpc.resp().propagated_hybrid_time());
  }

  // Check individual row errors.
  for (const WriteResponsePB_PerRowErrorPB& err_pb : rpc.resp().per_row_errors()) {
    // TODO: handle case where we get one of the more specific TS errors
    // like the tablet not being hosted?

    if (err_pb.row_index() >= rpc.ops().size()) {
      LOG_WITH_PREFIX(ERROR) << "Received a per_row_error for an out-of-bound op index "
                             << err_pb.row_index() << " (sent only "
                             << rpc.ops().size() << " ops)";
      LOG_WITH_PREFIX(ERROR) << "Response from tablet " << rpc.tablet().tablet_id() << ":\n"
                 << rpc.resp().DebugString();
      continue;
    }
    shared_ptr<YBOperation> yb_op = rpc.ops()[err_pb.row_index()]->yb_op;
    VLOG_WITH_PREFIX(1) << "Error on op " << yb_op->ToString() << ": "
                        << err_pb.error().ShortDebugString();
    std::lock_guard<decltype(mutex_)> lock(mutex_);
    CombineErrorUnlocked(rpc.ops()[err_pb.row_index()], StatusFromPB(err_pb.error()));
  }
}

double Batcher::RejectionScore(int attempt_num) {
  if (!rejection_score_source_) {
    return 0.0;
  }

  return rejection_score_source_->Get(attempt_num);
}

CollectedErrors Batcher::GetAndClearPendingErrors() {
  return error_collector_.GetAndClearErrors();
}

std::string Batcher::LogPrefix() const {
  const void* self = this;
  return Format("Batcher ($0): ", self);
}

BatcherState Batcher::state() const {
  std::lock_guard<decltype(mutex_)> lock(mutex_);
  return state_;
}

}  // namespace internal
}  // namespace client
}  // namespace yb


text:
// Software License for MTL
//
// Copyright (c) 2007 The Trustees of Indiana University.
//               2008 Dresden University of Technology and the Trustees of Indiana University.
//               2010 SimuNova UG (haftungsbeschränkt), www.simunova.com.
// All rights reserved.
// Authors: Peter Gottschling and Andrew Lumsdaine
//
// This file is part of the Matrix Template Library
//
// See also license.mtl.txt in the distribution.

#include <iostream>
#include <boost/numeric/mtl/mtl.hpp>

using namespace std;

template <typename Matrix>
void test(Matrix& A, const char* name)
{
    using mtl::Collection; using mtl::mat::inserter; using mtl::operations::update_plus;

    typedef typename Collection<Matrix>::value_type   value_type;

    value_type array[][3]= {{3, 7.2, 0}, {2, 4.444, 5}};
    A= array;

    std::cout << "\n" << name << ", assignment: A = \n" << A << "\n";

    MTL_THROW_IF(num_rows(A) != 2 || num_cols(A) != 3, mtl::runtime_error("Wrong matrix size"));
    MTL_THROW_IF(A[1][0] != value_type(2), mtl::runtime_error("Wrong value inserted"));

    {
	inserter<Matrix>  ins(A);
	ins(1, 0)+= 1.;
	//ins[1][0]+= 1.;
    }
    std::cout << "\n" << name << ", assignment: A = \n" << A << "\n";
    MTL_THROW_IF(A[1][0] != value_type(3.0), mtl::runtime_error("Wrong value after +="));

    {
	inserter<Matrix, update_plus<value_type> > ins(A, 0);
	ins(1, 2)= 4;
	ins[1][2]= 4;
	//ins[1, 2]= 4;
    }
    std::cout << "\n" << name << ", assignment: A = \n" << A << "\n";
    MTL_THROW_IF(A[1][2] != value_type(4.0), mtl::runtime_error("Wrong value after ="));
}

int main(int, char**)
{
    using namespace mtl;

    dense2D<double>                                      dr;
    dense2D<double, mat::parameters<col_major> >      dc;
    morton_dense<double, recursion::morton_z_mask>       mzd;
    morton_dense<double, recursion::doppled_2_row_mask>  d2r;
    compressed2D<double>                                 cr;
    compressed2D<double, mat::parameters<col_major> > cc;

    dense2D<complex<double> >                            drc;
    compressed2D<complex<double> >                       crc;

    test(dr, "Dense row major");
    test(dc, "Dense column major");
    test(mzd, "Morton Z-order");
    test(d2r, "Hybrid 2 row-major");
    test(cr, "Compressed row major");
    test(cc, "Compressed column major");
    test(drc, "Dense row major complex");
    test(crc, "Compressed row major complex");

    return 0;
}

ext: cpp


text:
// Copyright (c) 2012 by Raytheon BBN Technologies Corp.
// All Rights Reserved.

#include "Generic/common/leak_detection.h"

#include "Generic/theories/SynNode.h"

#include "English/edt/MentionGroups/extractors/en_ParentheticalPairExtractor.h"
#include "Generic/edt/MentionGroups/LinkInfoCache.h"

#include <boost/foreach.hpp>

EnglishParentheticalPairExtractor::EnglishParentheticalPairExtractor() :
	AttributeValuePairExtractor<MentionPair>(Symbol(L"MentionPair"), Symbol(L"parenthetical"))
{
	validateRequiredParameters();
}

std::vector<AttributeValuePair_ptr> EnglishParentheticalPairExtractor::extractFeatures(const MentionPair& context,
																			  LinkInfoCache& cache,
																			  const DocTheory *docTheory)
{
	std::vector<AttributeValuePair_ptr> results;

	const Mention *m1 = context.first;
	const Mention *m2 = context.second;

	// Only examine special parenthetical mentions that occur right after the other mention, or the last contained part of the other mention
	if (m1->getSentenceNumber() == m2->getSentenceNumber() && m2->getEntityType() == Symbol(L"POG")) {
		if (m1->getNode() &&
			m2->getNode() &&
			(m2->getNode()->getStartToken() == m1->getNode()->getEndToken() + 2 ||
			 (m2->getNode()->getParent() &&
			  m2->getNode()->getParent()->getParent() == m1->getNode() &&
			  m2->getNode()->getEndToken() + 1 == m1->getNode()->getEndToken()))) {
			results.push_back(AttributeValuePair<bool>::create(m2->getEntitySubtype().getName(), true, getFullName()));
		}
	}

	return results;
}

max_stars_repo_name: BBN-E/serif

max_issues_repo_name: BBN-E/serif

max_forks_repo_name: BBN-E/serif


text:
#include "crit_crauser.hpp"
#include "crit_dijkstra.hpp"
#include "crit_heuristic.hpp"
#include "crit_oracle.hpp"
#include "crit_traff_bridge.hpp"
#include "crit_paper_in.hpp"
#include "crit_paper_out.hpp"
#include "graph.hpp"
#include "test_graph.hpp"
#include <boost/mpl/list.hpp>
#include <boost/test/data/test_case.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/test/unit_test.hpp>
#include <cfloat>

using namespace sssp;

namespace {

struct crauser_in_static : crauser_in {
    crauser_in_static(const sssp::graph* g, size_t s) : crauser_in(g, s, false) {}
};

struct crauser_in_dynamic : crauser_in {
    crauser_in_dynamic(const sssp::graph* g, size_t s) : crauser_in(g, s, true) {}
};

struct crauser_out_static : crauser_out {
    crauser_out_static(const sssp::graph* g, size_t s) : crauser_out(g, s, false) {}
};

struct crauser_out_dynamic : crauser_out {
    crauser_out_dynamic(const sssp::graph* g, size_t s) : crauser_out(g, s, true) {}
};

} // namespace

using non_euclidean_tests = boost::mpl::list<paper_out,
                                             paper_in,
                                             traff_bridge,
                                             crauser_out_static,
                                             crauser_out_dynamic,
                                             crauser_in_static,
                                             crauser_in_dynamic,
                                             oracle,
                                             smallest_tentative_distance>;

#ifdef NDEBUG
static constexpr int test_count = 1000;
#else
// Debug builds are very slow and the tests need ages to run through.
static constexpr int test_count = 100;
#endif

BOOST_AUTO_TEST_CASE_TEMPLATE(criteria_non_euclidean_test, Criteria, non_euclidean_tests) {
    for (int seed = 0; seed < test_count; ++seed) {
        BOOST_TEST_CONTEXT("seed = " << seed) {
            const graph g = make_test_graph(seed);

            boost::base_collection<criteria> cs;
            cs.insert(Criteria(&g, 0));
            if (!cs.cbegin()->is_complete()) {
                cs.insert(smallest_tentative_distance(&g, 0));
            }
            node_map<dijkstra_result> result = dijkstra(g, 0, cs);

            cs.clear();
            cs.insert(smallest_tentative_distance(&g, 0));
            node_map<dijkstra_result> reference = dijkstra(g, 0, cs);

            for (size_t node = 0; node < g.node_count(); ++node) {
                BOOST_TEST_CONTEXT("node = " << node) {
                    BOOST_REQUIRE(reference[node].predecessor == result[node].predecessor);
                    BOOST_REQUIRE((reference[node].distance == result[node].distance ||
                                   std::abs(reference[node].distance - result[node].distance) <= DBL_EPSILON));
                }
            }
        }
    }
}

BOOST_AUTO_TEST_CASE_TEMPLATE(traffs_counter_example, Criteria, non_euclidean_tests) {
    //          5 --8--> 4 --3
    //                       |  /-- 1 --> 6
    //                       v /
    // 1 <--100-- 0 --110--> 2 <--\
    //            \--105--> 3 --2-/
    graph g;
    for (size_t i = 0; i <= 6; ++i) {
        g.add_node();
    }
    g.add_edge(0, 1, 100);
    g.add_edge(0, 2, 110);
    g.add_edge(0, 3, 105);
    g.add_edge(2, 6, 1);
    g.add_edge(3, 2, 2);
    g.add_edge(4, 2, 3);
    g.add_edge(5, 4, 8);

    boost::base_collection<criteria> cs;
    cs.insert(Criteria(&g, 0));
    if (!cs.cbegin()->is_complete()) {
        cs.insert(smallest_tentative_distance(&g, 0));
    }
    node_map<dijkstra_result> result = dijkstra(g, 0, cs);

    cs.clear();
    cs.insert(smallest_tentative_distance(&g, 0));
    node_map<dijkstra_result> reference = dijkstra(g, 0, cs);

    for (size_t node = 0; node < g.node_count(); ++node) {
        BOOST_TEST_CONTEXT("node = " << node) {
            BOOST_REQUIRE(reference[node].predecessor == result[node].predecessor);
            BOOST_REQUIRE((reference[node].distance == result[node].distance ||
                           std::abs(reference[node].distance - result[node].distance) <= DBL_EPSILON));
        }
    }
}

BOOST_AUTO_TEST_CASE(critiera_heuristic_tests) {
    for (int seed = 0; seed < test_count; ++seed) {
        BOOST_TEST_CONTEXT("seed = " << seed) {
            const auto g = make_test_graph_euclidean(seed);

            boost::base_collection<criteria> cs;
            auto h = [&](size_t node) { return distance(std::get<1>(g)[node], std::get<1>(g)[0]); };
            cs.insert(heuristic(&std::get<0>(g), 0, h));
            // This criteria is incomplete, therefore I add another one to make it complete.
            cs.insert(smallest_tentative_distance(&std::get<0>(g), 0));
            node_map<dijkstra_result> result = dijkstra(std::get<0>(g), 0, cs);

            cs.clear();
            cs.insert(smallest_tentative_distance(&std::get<0>(g), 0));
            node_map<dijkstra_result> reference = dijkstra(std::get<0>(g), 0, cs);

            for (size_t node = 0; node < std::get<0>(g).node_count(); ++node) {
                BOOST_TEST_CONTEXT("node = " << node) {
                    BOOST_REQUIRE(reference[node].predecessor == result[node].predecessor);
                    BOOST_REQUIRE((reference[node].distance == result[node].distance ||
                                   std::abs(reference[node].distance - result[node].distance) <= DBL_EPSILON));
                }
            }
        }
    }
}

max_stars_repo_name: kaini/sssp-simulation

max_issues_repo_name: kaini/sssp-simulation

max_forks_repo_name: kaini/sssp-simulation


text:
#pragma once

#include <fstream>

#include <boost/format.hpp>

#include <core/core.hpp>
#include <storage/archive.hpp>
#include <util/uuid.hpp>

namespace my {

class Resource : private boost::noncopyable {
  public:
    explicit Resource() {}
    virtual ~Resource() = default;
    const uuid &id() { return this->_uuid; }

    /**
     * @brief      resource memory size
     */
    virtual size_t used_mem() = 0;

  private:
    const uuid _uuid{uuid_gen()};
};

unique_ptr<std::ifstream> make_ifstream(const fs::path &path);

unique_ptr<std::ofstream> make_ofstream(const fs::path &path);

struct ResourceFileProvideInfo {
    fs::path path;
    size_t offset{0};
};
struct ResourceStreamProvideInfo {
    /**
     * only hint
     */
    size_t size{0};
    size_t offset{0};
    unique_ptr<std::istream> is{};
    static ResourceStreamProvideInfo make(const ResourceFileProvideInfo &info) {
        return ResourceStreamProvideInfo{fs::file_size(info.path), info.offset,
                                         make_ifstream(info.path)};
    }
};

class ResourceLocator {
  public:
    virtual ~ResourceLocator() = default;
    virtual std::string get_id() = 0;
    virtual bool exist() = 0;
    virtual std::optional<ResourceFileProvideInfo> make_file_provide_info() = 0;
    virtual std::optional<ResourceStreamProvideInfo>
    make_stream_provide_info() = 0;

    void set_offset(size_t offset) { this->offset = offset; }

  protected:
    size_t offset{0};
};

class FSResourceLocator : public ResourceLocator {
  public:
    fs::path path;

    FSResourceLocator(const fs::path &path) : path(path) {}

    static shared_ptr<FSResourceLocator> make(const fs::path &path) {
        return std::make_shared<FSResourceLocator>(path);
    }

    std::string get_id() override {
        return (boost::format("file://%1%?offset=%2%") %
                fs::absolute(this->path).string() % this->offset)
            .str();
    }

    bool exist() override { return fs::exists(this->path); }

    std::optional<ResourceFileProvideInfo> make_file_provide_info() override {
        return ResourceFileProvideInfo{this->path, this->offset};
    }
    std::optional<ResourceStreamProvideInfo>
    make_stream_provide_info() override {
        return ResourceStreamProvideInfo::make(
            FSResourceLocator::make_file_provide_info().value());
    }
};

struct ResourceLocatorError : public std::invalid_argument {
    ResourceLocatorError(const std::string &msg) : std::invalid_argument(msg) {}
};

class XP3ResourceLocator : public ResourceLocator {
  public:
    using archive_map = std::map<fs::path, shared_ptr<Archive>>;
    using make_archive_map = std::map<std::string, Archive::make_archive_func>;

    fs::path archive_path;
    fs::path query_path;

    XP3ResourceLocator(const fs::path &archive_path, const fs::path &query_path)
        : archive_path(archive_path), query_path(query_path) {}

    static shared_ptr<XP3ResourceLocator> make(const fs::path &archive_path,
                                               const fs::path &query_path) {
        return std::make_shared<XP3ResourceLocator>(archive_path, query_path);
    }

    std::string get_id() override {
        return (boost::format("file://%1%?query=%2%&offset=%3%") %
                fs::absolute(this->archive_path).string() %
                this->query_path.string() % this->offset)
            .str();
    }

    bool exist() override {
        return this->archive_get()->exists(this->query_path);
    }

    std::optional<ResourceFileProvideInfo> make_file_provide_info() override {
        return std::nullopt;
    }

    std::optional<ResourceStreamProvideInfo>
    make_stream_provide_info() override {
        auto archive_file = this->archive_get()->extract(this->query_path);
        return ResourceStreamProvideInfo{archive_file.org_size, this->offset,
                                         std::move(archive_file.is)};
    }

  private:
    static const make_archive_map _supported_archives;

    std::optional<shared_ptr<Archive>>
    archive_get_if_exist(const fs::path &path) {
        const auto extension = path.extension();
        auto it = XP3ResourceLocator::_supported_archives.find(extension);
        if (it != XP3ResourceLocator::_supported_archives.end() &&
            FSResourceLocator::make(path)->exist()) {
            return it->second(path);
        }
        return std::nullopt;
    }

    shared_ptr<Archive> archive_get() {
        auto archive =
            XP3ResourceLocator::archive_get_if_exist(this->archive_path);
        if (!archive.has_value()) {
            throw ResourceLocatorError(
                (boost::format("archive %1% is not exist") % this->archive_path)
                    .str());
        }
        return archive.value();
    }
};

template <typename res,
          typename = std::enable_if_t<std::is_base_of_v<Resource, res>>>
class ResourceProvider {
    /**
     * @brief      load from fs
     */
    static shared_ptr<res> load(const ResourceFileProvideInfo &) {
        throw std::invalid_argument((boost::format("%1% can not be load") %
                                     ResourceProvider<res>::type().name)
                                        .str());
    }

    /**
     * @brief      load from stream
     */
    static shared_ptr<res> load(const ResourceStreamProvideInfo &) {
        throw std::invalid_argument((boost::format("%1% can not be load") %
                                     ResourceProvider<res>::type().name)
                                        .str());
    }
};

} // namespace my

ext: hpp

max_stars_repo_name: yydcnjjw/my-gui

max_issues_repo_name: yydcnjjw/my-gui

max_forks_repo_name: yydcnjjw/my-gui


text:
//==============================================================================
//         Copyright 2003 - 2011 LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2011 LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef NT2_TRIGONOMETRIC_FUNCTIONS_SCALAR_TANGENT_HPP_INCLUDED
#define NT2_TRIGONOMETRIC_FUNCTIONS_SCALAR_TANGENT_HPP_INCLUDED
#include <nt2/trigonometric/functions/tangent.hpp>
#include <nt2/trigonometric/functions/scalar/impl/trigo.hpp>
#include <nt2/trigonometric/functions/simd/common/impl/trigo.hpp>
#include <boost/simd/sdk/simd/meta/is_native.hpp>
#include <nt2/include/functions/simd/tofloat.hpp>
#include <nt2/sdk/meta/as_floating.hpp>

namespace nt2 { namespace ext
{
  NT2_FUNCTOR_IMPLEMENTATION( nt2::tag::tangent_<mode>, tag::cpu_
                            , (A0)(mode)
                            , (scalar_< arithmetic_<A0> >)
                            )
  {

    typedef typename boost::dispatch::meta::as_floating<A0>::type result_type;

    NT2_FUNCTOR_CALL(1)
    {
      return nt2::tangent<mode>(nt2::tofloat(a0));
    }
  };

  NT2_FUNCTOR_IMPLEMENTATION( nt2::tag::tangent_<mode> , tag::cpu_
                            , (A0)(mode)
                            , (scalar_< floating_<A0> >)
                            )
  {
    typedef A0 result_type;
    NT2_FUNCTOR_CALL(1)
    {
      return impl::trig_base<A0,radian_tag,tag::not_simd_type,mode>::tana(a0);
    }
  };
} }

#endif


text:
#include <iostream>
#include <armadillo>

using namespace std;
using namespace arma;

vec addTwo_parallel(vec x, vec y){
    vec z(x.n_elem);
    int i;
#pragma omp parallel for schedule(static) \
private(i) shared(x,y,z)
    for(i=0; i < x.n_elem; i++)
        z(i) = x(i) + 2 * y(i);
    return z;
}

int main()
{

    vec a = ones<vec>(10);
    vec b = ones<vec>(10);
    vec c = addTwo_parallel(a, b);
    c.print();
    return 0;
}


text:
/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MemoryDB.cpp
 * @author Christoph Jentzsch <cj@ethdev.com>
 * @date 2015
 * memDB test functions.
 */

#include <boost/test/unit_test.hpp>
#include <iostream>
#include <libdevcore/MemoryDB.h>
#include <test/libtesteth/TestHelper.h>

using namespace std;
using namespace dev;
using namespace dev::test;

namespace dev {  namespace test {

} }// Namespace Close

BOOST_FIXTURE_TEST_SUITE(memDB, TestOutputHelper)

BOOST_AUTO_TEST_CASE(kill)
{
	MemoryDB myDB;
	BOOST_CHECK(myDB.get().empty());
	bytes value = fromHex("43");
	myDB.insert(h256(42), &value);
	BOOST_CHECK(myDB.exists(h256(42)));
	BOOST_CHECK_EQUAL(myDB.get().size(), 1);
	BOOST_CHECK(!myDB.kill(h256(43)));
	BOOST_CHECK(myDB.kill(h256(42)));
}

BOOST_AUTO_TEST_CASE(purgeMainMem)
{
	MemoryDB myDB;
	BOOST_CHECK(myDB.get().empty());
	bytes value = fromHex("43");

	myDB.insert(h256(42), &value);
	MemoryDB copy;
	copy = myDB;
	BOOST_CHECK(myDB.exists(h256(42)));
	BOOST_CHECK_EQUAL(myDB.lookup(h256(42)), toString(value[0]));
	BOOST_CHECK_EQUAL(myDB.get().size(), 1);
	BOOST_CHECK(myDB.kill(h256(42)));

	BOOST_CHECK(myDB.get() == copy.get());
	BOOST_CHECK(myDB.exists(h256(42)));
	BOOST_CHECK_EQUAL(myDB.lookup(h256(42)), toString(value[0]));

	BOOST_CHECK_EQUAL(myDB.get().size(), 1);
	myDB.purge();
	BOOST_CHECK_EQUAL(myDB.get().size(), 0);
	myDB.insert(h256(43), &value);
	BOOST_CHECK_EQUAL(myDB.get().size(), 1);
	myDB.clear();
	BOOST_CHECK_EQUAL(myDB.get().size(), 0);
}

BOOST_AUTO_TEST_CASE(purgeMainMem_Refs)
{
	MemoryDB myDB;
	{
		EnforceRefs enforceRefs(myDB, true);

		BOOST_CHECK(myDB.get().empty());
		bytes value = fromHex("43");

		myDB.insert(h256(42), &value);
		MemoryDB copy;
		copy = myDB;
		BOOST_CHECK(myDB.exists(h256(42)));
		BOOST_CHECK_EQUAL(myDB.lookup(h256(42)), toString(value[0]));
		BOOST_CHECK_EQUAL(myDB.get().size(), 1);
		BOOST_CHECK(myDB.kill(h256(42)));

		BOOST_CHECK(myDB.get() != copy.get());
		BOOST_CHECK(!myDB.exists(h256(42)));
		BOOST_CHECK_EQUAL(myDB.lookup(h256(42)), std::string());

		BOOST_CHECK_EQUAL(myDB.get().size(), 0);
		myDB.purge();
		BOOST_CHECK_EQUAL(myDB.get().size(), 0);
		myDB.insert(h256(43), &value);
		BOOST_CHECK_EQUAL(myDB.get().size(), 1);
		myDB.clear();
		BOOST_CHECK_EQUAL(myDB.get().size(), 0);
		// call EnforceRefs destructor
	}

	// do same tests again without EnforceRefs
	BOOST_CHECK(myDB.get().empty());
	bytes value = fromHex("43");

	myDB.insert(h256(42), &value);
	MemoryDB copy;
	copy = myDB;
	BOOST_CHECK(myDB.exists(h256(42)));
	BOOST_CHECK_EQUAL(myDB.lookup(h256(42)), toString(value[0]));
	BOOST_CHECK_EQUAL(myDB.get().size(), 1);
	BOOST_CHECK(myDB.kill(h256(42)));

	BOOST_CHECK(myDB.get() == copy.get());
	BOOST_CHECK(myDB.exists(h256(42)));
	BOOST_CHECK_EQUAL(myDB.lookup(h256(42)), toString(value[0]));

	BOOST_CHECK_EQUAL(myDB.get().size(), 1);
	myDB.purge();
	BOOST_CHECK_EQUAL(myDB.get().size(), 0);
	myDB.insert(h256(43), &value);
	BOOST_CHECK_EQUAL(myDB.get().size(), 1);
	myDB.clear();
	BOOST_CHECK_EQUAL(myDB.get().size(), 0);
}

BOOST_AUTO_TEST_CASE(purgeAuxMem)
{
	class AuxMemDB : public MemoryDB
	{
	public:
		std::unordered_map<h256, std::pair<bytes, bool>> getAux() { return m_aux;}
	};

	AuxMemDB myDB;
	BOOST_CHECK(myDB.get().empty());
	bytes value = fromHex("43");

	myDB.insertAux(h256(42), &value);
	BOOST_CHECK(myDB.lookupAux(h256(42)) == value);
	BOOST_CHECK_EQUAL(myDB.get().size(), 0);
	myDB.removeAux(h256(42));
	BOOST_CHECK(myDB.lookupAux(h256(42)) == value);
	BOOST_CHECK_EQUAL(myDB.getAux().size(), 1);
	myDB.purge();
	BOOST_CHECK(myDB.lookupAux(h256(42)) == bytes());
	BOOST_CHECK_EQUAL(myDB.getAux().size(), 0);
	myDB.insertAux(h256(43), &value);
	BOOST_CHECK_EQUAL(myDB.getAux().size(), 1);
	myDB.clear();
	BOOST_CHECK_EQUAL(myDB.getAux().size(), 0);
}

BOOST_AUTO_TEST_CASE(copy)
{
	MemoryDB myDB;
	BOOST_CHECK(myDB.get().empty());
	bytes value = fromHex("43");
	myDB.insert(h256(42), &value);
	BOOST_CHECK(myDB.exists(h256(42)));
	BOOST_CHECK_EQUAL(myDB.get().size(), 1);

	MemoryDB copyToDB;
	copyToDB = myDB;
	BOOST_CHECK(copyToDB.exists(h256(42)));
	BOOST_CHECK_EQUAL(copyToDB.get().size(), 1);
	BOOST_CHECK(myDB.keys() == copyToDB.keys());
	BOOST_CHECK(myDB.get() == copyToDB.get());
	myDB.insert(h256(43), &value);
	BOOST_CHECK(myDB.keys() != copyToDB.keys());
}

BOOST_AUTO_TEST_CASE(lookUp)
{
	MemoryDB myDB;
	BOOST_CHECK(myDB.get().empty());
	bytes value = fromHex("43");

	myDB.insert(h256(42), &value);
	BOOST_CHECK(myDB.exists(h256(42)));
	BOOST_CHECK_EQUAL(myDB.lookup(h256(42)), toString(value[0]));
	BOOST_CHECK_EQUAL(myDB.get().size(), 1);

	myDB.insert(h256(0), &value);
	BOOST_CHECK(myDB.exists(h256(0)));
	BOOST_CHECK_EQUAL(myDB.lookup(h256(0)), toString(value[0]));

	myDB.insert(h256(std::numeric_limits<u256>::max()), &value);
	BOOST_CHECK(myDB.exists(h256(std::numeric_limits<u256>::max())));
	BOOST_CHECK_EQUAL(myDB.lookup(h256(std::numeric_limits<u256>::max())), toString(value[0]));

	BOOST_CHECK_EQUAL(myDB.get().size(), 3);
}

BOOST_AUTO_TEST_CASE(stream)
{
	MemoryDB myDB;
	BOOST_CHECK(myDB.get().empty());
	bytes value = fromHex("43");
	myDB.insert(h256(42), &value);
	myDB.insert(h256(43), &value);
	std::ostringstream stream;
	stream << myDB;
	BOOST_CHECK_EQUAL(stream.str(), "000000000000000000000000000000000000000000000000000000000000002a: 0x43 43\n000000000000000000000000000000000000000000000000000000000000002b: 0x43 43\n");
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: XianlinGong/fabcoinsc-dev

max_issues_repo_name: XianlinGong/fabcoinsc-dev

max_forks_repo_name: XianlinGong/fabcoinsc-dev


text:
// Copyright 2021 Oxford Technical Solutions Ltd.
//
// 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 <array>
#include <boost/test/unit_test.hpp>
#include <chrono>
#include <cstring>
#include <future>
#include <memory>

#include "oxts_driver/udp_server_client.h"

using namespace std::literals;

namespace tests::udp_server_client {

const short PORT_NUMBER = 12345;

std::unique_ptr<networking_udp::client> client;
std::unique_ptr<networking_udp::server> server;

constexpr int MESSAGE_LEN = 13;
networking_udp::byte MESSAGE[MESSAGE_LEN] = "hello, world";

struct Fixture {
  Fixture() {
    client = std::make_unique<networking_udp::client>(PORT_NUMBER);
    server = std::make_unique<networking_udp::server>();
    server->set_remote_endpoint("127.0.0.1", PORT_NUMBER);
  }
};

BOOST_AUTO_TEST_SUITE(udp_server_client, *boost::unit_test::fixture<Fixture>())

BOOST_AUTO_TEST_CASE(sendReceive) {
  auto future = std::async(std::launch::async, []() {
    auto received = std::array<networking_udp::byte, MESSAGE_LEN>{};
    client->receive(received.data(), MESSAGE_LEN);
    return received;
  });
  std::this_thread::sleep_for(100ms); // race conditions; just in case

  server->send(MESSAGE, MESSAGE_LEN);

  auto received = future.get();
  BOOST_CHECK(std::strncmp((const char *)received.data(), (const char *)MESSAGE,
                           MESSAGE_LEN) == 0);
}

BOOST_AUTO_TEST_CASE(sendTo) {
  using namespace boost::asio::ip;

  auto future = std::async(std::launch::async, []() {
    auto received = std::array<networking_udp::byte, MESSAGE_LEN>{};
    client->receive(received.data(), MESSAGE_LEN);
    return received;
  });
  std::this_thread::sleep_for(100ms); // race conditions; just in case

  server->send_to(
      MESSAGE, MESSAGE_LEN,
      udp::endpoint{address::from_string("127.0.0.1"), PORT_NUMBER});

  auto received = future.get();
  BOOST_CHECK(std::strncmp((const char *)received.data(), (const char *)MESSAGE,
                           MESSAGE_LEN) == 0);
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace tests::udp_server_client


text:
#include <functional>
#include <iostream>
#include <string_view>
#include <boost/program_options.hpp>

#include <IO/ReadBufferFromFileDescriptor.h>
#include <IO/ReadHelpers.h>
#include <IO/WriteBufferFromFileDescriptor.h>
#include <IO/WriteBufferFromOStream.h>
#include <Parsers/ASTInsertQuery.h>
#include <Parsers/ParserQuery.h>
#include <Parsers/formatAST.h>
#include <Parsers/obfuscateQueries.h>
#include <Parsers/parseQuery.h>
#include <Common/ErrorCodes.h>
#include <Common/TerminalSize.h>

#include <Interpreters/Context.h>
#include <Functions/FunctionFactory.h>
#include <Functions/registerFunctions.h>
#include <AggregateFunctions/AggregateFunctionFactory.h>
#include <AggregateFunctions/registerAggregateFunctions.h>
#include <TableFunctions/TableFunctionFactory.h>
#include <TableFunctions/registerTableFunctions.h>
#include <Storages/StorageFactory.h>
#include <Storages/registerStorages.h>
#include <DataTypes/DataTypeFactory.h>
#include <Formats/FormatFactory.h>
#include <Formats/registerFormats.h>

#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wmissing-declarations"

namespace DB
{
namespace ErrorCodes
{
extern const int INVALID_FORMAT_INSERT_QUERY_WITH_DATA;
}
}

int mainEntryClickHouseFormat(int argc, char ** argv)
{
    using namespace DB;

    try
    {
        boost::program_options::options_description desc = createOptionsDescription("Allowed options", getTerminalWidth());
        desc.add_options()
            ("query", po::value<std::string>(), "query to format")
            ("help,h", "produce help message")
            ("hilite", "add syntax highlight with ANSI terminal escape sequences")
            ("oneline", "format in single line")
            ("quiet,q", "just check syntax, no output on success")
            ("multiquery,n", "allow multiple queries in the same file")
            ("obfuscate", "obfuscate instead of formatting")
            ("backslash", "add a backslash at the end of each line of the formatted query")
            ("allow_settings_after_format_in_insert", "Allow SETTINGS after FORMAT, but note, that this is not always safe")
            ("seed", po::value<std::string>(), "seed (arbitrary string) that determines the result of obfuscation")
        ;

        Settings cmd_settings;
        for (const auto & field : cmd_settings.all())
        {
            if (field.getName() == "max_parser_depth" || field.getName() == "max_query_size")
                cmd_settings.addProgramOption(desc, field);
        }

        boost::program_options::variables_map options;
        boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), options);
        po::notify(options);

        if (options.count("help"))
        {
            std::cout << "Usage: " << argv[0] << " [options] < query" << std::endl;
            std::cout << desc << std::endl;
            return 1;
        }

        bool hilite = options.count("hilite");
        bool oneline = options.count("oneline");
        bool quiet = options.count("quiet");
        bool multiple = options.count("multiquery");
        bool obfuscate = options.count("obfuscate");
        bool backslash = options.count("backslash");
        bool allow_settings_after_format_in_insert = options.count("allow_settings_after_format_in_insert");

        if (quiet && (hilite || oneline || obfuscate))
        {
            std::cerr << "Options 'hilite' or 'oneline' or 'obfuscate' have no sense in 'quiet' mode." << std::endl;
            return 2;
        }

        if (obfuscate && (hilite || oneline || quiet))
        {
            std::cerr << "Options 'hilite' or 'oneline' or 'quiet' have no sense in 'obfuscate' mode." << std::endl;
            return 2;
        }

        String query;

        if (options.count("query"))
        {
            query = options["query"].as<std::string>();
        }
        else
        {
            ReadBufferFromFileDescriptor in(STDIN_FILENO);
            readStringUntilEOF(query, in);
        }

        if (obfuscate)
        {
            WordMap obfuscated_words_map;
            WordSet used_nouns;
            SipHash hash_func;

            if (options.count("seed"))
            {
                std::string seed;
                hash_func.update(options["seed"].as<std::string>());
            }

            registerFunctions();
            registerAggregateFunctions();
            registerTableFunctions();
            registerStorages();
            registerFormats();

            std::unordered_set<std::string> additional_names;

            auto all_known_storage_names = StorageFactory::instance().getAllRegisteredNames();
            auto all_known_data_type_names = DataTypeFactory::instance().getAllRegisteredNames();

            additional_names.insert(all_known_storage_names.begin(), all_known_storage_names.end());
            additional_names.insert(all_known_data_type_names.begin(), all_known_data_type_names.end());

            KnownIdentifierFunc is_known_identifier = [&](std::string_view name)
            {
                std::string what(name);

                return FunctionFactory::instance().has(what)
                    || AggregateFunctionFactory::instance().isAggregateFunctionName(what)
                    || TableFunctionFactory::instance().isTableFunctionName(what)
                    || FormatFactory::instance().isOutputFormat(what)
                    || FormatFactory::instance().isInputFormat(what)
                    || additional_names.count(what);
            };

            WriteBufferFromFileDescriptor out(STDOUT_FILENO);
            obfuscateQueries(query, out, obfuscated_words_map, used_nouns, hash_func, is_known_identifier);
        }
        else
        {
            const char * pos = query.data();
            const char * end = pos + query.size();

            ParserQuery parser(end, allow_settings_after_format_in_insert);
            do
            {
                ASTPtr res = parseQueryAndMovePosition(
                    parser, pos, end, "query", multiple, cmd_settings.max_query_size, cmd_settings.max_parser_depth);
                /// For insert query with data(INSERT INTO ... VALUES ...), will lead to format fail,
                /// should throw exception early and make exception message more readable.
                if (const auto * insert_query = res->as<ASTInsertQuery>(); insert_query && insert_query->data)
                {
                    throw Exception(
                        "Can't format ASTInsertQuery with data, since data will be lost",
                        DB::ErrorCodes::INVALID_FORMAT_INSERT_QUERY_WITH_DATA);
                }
                if (!quiet)
                {
                    if (!backslash)
                    {
                        WriteBufferFromOStream res_buf(std::cout, 4096);
                        formatAST(*res, res_buf, hilite, oneline);
                        res_buf.next();
                        if (multiple)
                            std::cout << "\n;\n";
                        std::cout << std::endl;
                    }
                    /// add additional '\' at the end of each line;
                    else
                    {
                        WriteBufferFromOwnString str_buf;
                        formatAST(*res, str_buf, hilite, oneline);

                        auto res_string = str_buf.str();
                        WriteBufferFromOStream res_cout(std::cout, 4096);

                        const char * s_pos= res_string.data();
                        const char * s_end = s_pos + res_string.size();

                        while (s_pos != s_end)
                        {
                            if (*s_pos == '\n')
                                res_cout.write(" \\", 2);
                            res_cout.write(*s_pos++);
                        }

                        res_cout.next();
                        if (multiple)
                            std::cout << " \\\n;\n";
                        std::cout << std::endl;
                    }
                }

                do
                {
                    /// skip spaces to avoid throw exception after last query
                    while (pos != end && std::isspace(*pos))
                        ++pos;

                    /// for skip comment after the last query and to not throw exception
                    if (end - pos > 2 && *pos == '-' && *(pos + 1) == '-')
                    {
                        pos += 2;
                        /// skip until the end of the line
                        while (pos != end && *pos != '\n')
                            ++pos;
                    }
                    /// need to parse next sql
                    else
                        break;
                } while (pos != end);

            } while (multiple && pos != end);
        }
    }
    catch (...)
    {
        std::cerr << getCurrentExceptionMessage(true) << '\n';
        return getCurrentExceptionCode();
    }
    return 0;
}

max_stars_repo_name: oliverdding/ClickHouse

max_issues_repo_name: oliverdding/ClickHouse

max_forks_repo_name: oliverdding/ClickHouse


text:
// Copyright 2015, 2016 Carnegie Mellon University.  See LICENSE file for terms.

#ifndef Pharos_Enums_H
#define Pharos_Enums_H

#include <iostream>
#include <locale>
#include <sstream>
#include <boost/algorithm/string.hpp>

#include "util.hpp"

// mwd: Consider replacing this with better-enums.  http://aantron.github.io/better-enums/

namespace pharos {

// This is the mechanism that allows the labels to be associated with a specific enum through a
// template.  See enumtest.cpp for example usage.
template<typename T>
struct EnumStrings
{
  static char const* data[];
};

// This routine converts an enum into a string using the appropriate (templated) label array.
// It's about as efficient as you can get, but it requires that your enums have no assigned
// values.  This means that the enums start at value zero and increases monotonically.
template<typename T> std::string Enum2Str(T value) {
  return  EnumStrings<T>::data[static_cast< ssize_t >(value)];
}

// This routine attempts to convert a case-insensitive string into an enum value by looking it
// up in the list of labels (which are also treated case insensitively).  If the value is not
// found, the provided default value is returned.  This routine is far from optimal, and has
// performance of O(n*m), where n is number of labels and m is the average length of a label.
// A better implementation would probably be to pre-compute all of the lowercase values, and to
// build a pair maps for O(log(n)) lookup.  Our enums are small, so don't prematurely optimize.
template<typename T>
T Str2Enum(const std::string & value, T default_value) noexcept {
  // Get a pointer to our templated array of labels.
  const char** label = EnumStrings<T>::data;

  // Determine how many labels there are.
  constexpr size_t maximum = sizeof(EnumStrings<T>::data) / sizeof(char *);

  // Walk the labels, looking for the provided label.
  bool found = false;
  size_t i;
  for (i = 0; i < maximum; i++) {
    // Lowercase the label as well.
    if (boost::iequals(label[i], value)) {
      found = true;
      break;
    }
  }

  // If the value was not found in the list of labels,
  // return the default value provided by the caller
  if (!found) return default_value;

  // Otherwise return the matched value.
  return T(i);
}

// This routine attempts to convert a case-insensitive string into an enum value by looking it
// up in the list of labels (which are also treated case insensitively).  If the value is not
// found, a runtime_error is thrown.
template<typename T>
T Str2Enum(const std::string & value)
{
  // Get a pointer to our templated array of labels.
  const char** label = EnumStrings<T>::data;

  // Determine how many labels there are.
  constexpr size_t maximum = sizeof(EnumStrings<T>::data) / sizeof(char *);

  // Walk the labels, looking for the provided label.
  bool found = false;
  size_t i;
  for (i = 0; i < maximum; i++) {
    if (boost::iequals(label[i], value)) {
      found = true;
      break;
    }
  }

  // If the value was not found in the list of labels,
  // return the default value provided by the caller
  if (!found) {
    std::ostringstream os;
    os << "Invalid enum value: " << value;
    throw std::runtime_error(os.str());
  }

  // Otherwise return the matched value.
  return static_cast<T>(i);
}

} // namespace pharos

#endif
/* Local Variables:   */
/* mode: c++          */
/* fill-column:    95 */
/* comment-column: 0  */
/* End:               */

max_stars_repo_name: tjschweizer/pharos

max_issues_repo_name: tjschweizer/pharos

max_forks_repo_name: tjschweizer/pharos


text:
//==============================================================================
//         Copyright 2003 - 2011 LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2011 LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef BOOST_SIMD_TOOLBOX_ARITHMETIC_FUNCTIONS_SIMD_COMMON_CORRECT_FMA_HPP_INCLUDED
#define BOOST_SIMD_TOOLBOX_ARITHMETIC_FUNCTIONS_SIMD_COMMON_CORRECT_FMA_HPP_INCLUDED
#include <boost/simd/toolbox/arithmetic/functions/correct_fma.hpp>
#include <boost/simd/include/functions/simd/multiplies.hpp>
#include <boost/simd/include/functions/simd/plus.hpp>
#include <boost/simd/include/functions/simd/two_prod.hpp>
#include <boost/simd/include/functions/simd/two_add.hpp>

/////////////////////////////////////////////////////////////////////////////
// Implementation when type A0 is arithmetic_
/////////////////////////////////////////////////////////////////////////////
namespace boost { namespace simd { namespace ext
{
  BOOST_SIMD_FUNCTOR_IMPLEMENTATION( boost::simd::tag::correct_fma_, tag::cpu_
                            , (A0)(X)
                            , ((simd_<arithmetic_<A0>,X>))((simd_<arithmetic_<A0>,X>))((simd_<arithmetic_<A0>,X>))
                            )
  {
    typedef A0 result_type;
    BOOST_SIMD_FUNCTOR_CALL_REPEAT(3)
    {
      return a0*a1+a2;
    }
  };

  BOOST_SIMD_FUNCTOR_IMPLEMENTATION( boost::simd::tag::correct_fma_, tag::cpu_
                            , (A0)(X)
                            , ((simd_<floating_<A0>,X>))
                              ((simd_<floating_<A0>,X>))
                              ((simd_<floating_<A0>,X>))
                            )
  {
    typedef A0 result_type;
    BOOST_SIMD_FUNCTOR_CALL_REPEAT(3)
    {
      A0 p, rp, s, rs;
      two_prod(a0, a1, p, rp);
      two_add(p, a2, s, rs);
      return s+(rp+rs);
    }
  };
} } }

#endif


text:
/**
 * Copyright Soramitsu Co., Ltd. 2018 All Rights Reserved.
 * http://soramitsu.co.jp
 *
 * 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 <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/indexed.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/numeric.hpp>
#include <unordered_set>

#include "ametsuchi/impl/postgres_block_index.hpp"
#include "common/types.hpp"
#include "common/visitor.hpp"
#include "cryptography/ed25519_sha3_impl/internal/sha3_hash.hpp"
#include "interfaces/commands/transfer_asset.hpp"
#include "interfaces/iroha_internal/block.hpp"

namespace iroha {
  namespace ametsuchi {

    PostgresBlockIndex::PostgresBlockIndex(pqxx::nontransaction &transaction)
        : transaction_(transaction),
          log_(logger::log("PostgresBlockIndex")),
          execute_{makeExecuteOptional(transaction_, log_)} {}

    auto PostgresBlockIndex::indexAccountIdHeight(const std::string &account_id,
                                                  const std::string &height) {
      return this->execute(
          "INSERT INTO height_by_account_set(account_id, height) "
          "VALUES ("
          + transaction_.quote(account_id) + ", " + transaction_.quote(height)
          + ");");
    }

    auto PostgresBlockIndex::indexAccountAssets(
        const std::string &account_id,
        const std::string &height,
        const std::string &index,
        const shared_model::interface::Transaction::CommandsType &commands) {
      // flat map abstract commands to transfers

      return std::accumulate(
          commands.begin(),
          commands.end(),
          true,
          [&](auto &status, const auto &cmd) {
            return visit_in_place(
                cmd.get(),
                [&](const shared_model::interface::TransferAsset &command) {
                  status &=
                      this->indexAccountIdHeight(command.srcAccountId(), height)
                      & this->indexAccountIdHeight(command.destAccountId(),
                                                   height);

                  auto ids = {account_id,
                              command.srcAccountId(),
                              command.destAccountId()};
                  // flat map accounts to unindexed keys
                  boost::for_each(ids, [&](const auto &id) {
                    auto res = execute_(
                        "INSERT INTO index_by_id_height_asset(id, "
                        "height, asset_id, "
                        "index) "
                        "VALUES ("
                        + transaction_.quote(id) + ", "
                        + transaction_.quote(height) + ", "
                        + transaction_.quote(command.assetId()) + ", "
                        + transaction_.quote(index) + ");");
                    status &= res != boost::none;
                  });
                  return status;
                },
                [&](const auto &command) { return true; });
          });
    }

    void PostgresBlockIndex::index(
        const shared_model::interface::Block &block) {
      const auto &height = std::to_string(block.height());
      boost::for_each(
          block.transactions() | boost::adaptors::indexed(0),
          [&](const auto &tx) {
            const auto &creator_id = tx.value().creatorAccountId();
            const auto &hash = tx.value().hash().blob();
            const auto &index = std::to_string(tx.index());

            // tx hash -> block where hash is stored
            this->execute("INSERT INTO height_by_hash(hash, height) VALUES ("
                          + transaction_.quote(
                                pqxx::binarystring(hash.data(), hash.size()))
                          + ", " + transaction_.quote(height) + ");");

            this->indexAccountIdHeight(creator_id, height);

            // to make index account_id:height -> list of tx indexes
            // (where tx is placed in the block)
            execute_(
                "INSERT INTO index_by_creator_height(creator_id, "
                "height, index) "
                "VALUES ("
                + transaction_.quote(creator_id) + ", "
                + transaction_.quote(height) + ", " + transaction_.quote(index)
                + ");");

            this->indexAccountAssets(
                creator_id, height, index, tx.value().commands());
          });
    }
  }  // namespace ametsuchi
}  // namespace iroha


text:
/*!
@file
Defines `boost::hana::integral_constant`.

@copyright Louis Dionne 2013-2016
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_HANA_INTEGRAL_CONSTANT_HPP
#define BOOST_HANA_INTEGRAL_CONSTANT_HPP

#include <boost/hana/bool.hpp>

#endif // !BOOST_HANA_INTEGRAL_CONSTANT_HPP

max_stars_repo_name: rudylee/expo

max_issues_repo_name: rudylee/expo

max_forks_repo_name: rudylee/expo


text:
/****************************************************************************
 *  hipipe library
 *  Copyright (c) 2017, Cognexa Solutions s.r.o.
 *  Copyright (c) 2018, Iterait a.s.
 *  Author(s) Filip Matzner
 *
 *  This file is distributed under the MIT License.
 *  See the accompanying file LICENSE.txt for the complete license agreement.
 ****************************************************************************/

#pragma once

#include <hipipe/build_config.hpp>

#include <boost/test/unit_test.hpp>

#include <range/v3/core.hpp>

namespace rg = ranges;
namespace rga = ranges::actions;
namespace rgv = ranges::views;

template<typename Rng1, typename Rng2>
void test_ranges_equal(Rng1&& rng1, Rng2&& rng2)
{
    // using this function, ranges with different
    // begin() and end() types can be compared
    auto it1 = rg::begin(rng1);
    auto it2 = rg::begin(rng2);
    while (it1 != rg::end(rng1) && it2 != rg::end(rng2)) {
        BOOST_TEST(*it1 == *it2);
        ++it1;
        ++it2;
    }
    BOOST_CHECK(it1 == rg::end(rng1));
    BOOST_CHECK(it2 == rg::end(rng2));
}

max_stars_repo_name: iterait/hipipe

max_issues_repo_name: iterait/hipipe

max_forks_repo_name: iterait/hipipe


text:
/**
 * @file lltoastalertpanel.cpp
 * @brief Panel for alert toasts.
 *
 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h" // must be first include

#include "linden_common.h"

#include "llboost.h"

#include "lltoastalertpanel.h"
#include "llfontgl.h"
#include "lltextbox.h"
#include "llbutton.h"
#include "llkeyboard.h"
#include "llfocusmgr.h"
#include "lliconctrl.h"
#include "llui.h"
#include "lllineeditor.h"
#include "lluictrlfactory.h"
#include "llnotifications.h"
#include "llrootview.h"
#include "lltransientfloatermgr.h"
#include "llviewercontrol.h" // for gSavedSettings
#include "llweb.h"

#include <boost/algorithm/string.hpp>

const S32 MAX_ALLOWED_MSG_WIDTH = 400;
const F32 DEFAULT_BUTTON_DELAY = 0.5f;

/*static*/ LLControlGroup* LLToastAlertPanel::sSettings = NULL;

//-----------------------------------------------------------------------------
// Private methods

static const S32 VPAD = 16;
static const S32 HPAD = 25;
static const S32 BTN_HPAD = 8;

LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal)
	  : LLCheckBoxToastPanel(notification),
		mDefaultOption( 0 ),
		mCaution(notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH),
		mLabel(notification->getName()),
		mLineEditor(NULL)
{
    // EXP-1822
    // save currently focused view, so that return focus to it
    // on destroying this toast.
    LLView* current_selection = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus());
    while(current_selection)
    {
        // <FS:Ansariel> FIRE-6651: Modal alert toasts don't restore focus properly
        //if (current_selection->isFocusRoot())
        if (current_selection->isFocusRoot() && (!dynamic_cast<LLFloater*>(current_selection) || !dynamic_cast<LLFloater*>(current_selection)->getHost()))
        // </FS:Ansariel>
        {
            mPreviouslyFocusedView = current_selection->getHandle();
            break;
        }
        current_selection = current_selection->getParent();
    }

	const LLFontGL* font = LLFontGL::getFontSansSerif();
	const S32 LINE_HEIGHT = font->getLineHeight();
	const S32 EDITOR_HEIGHT = 20;

	LLNotificationFormPtr form = mNotification->getForm();
	std::string edit_text_name;
	std::string edit_text_contents;
	S32 edit_text_max_chars = 0;
	bool is_password = false;
	bool defaultText = false;

	LLToastPanel::setBackgroundVisible(FALSE);
	LLToastPanel::setBackgroundOpaque(TRUE);

	typedef std::vector<std::pair<std::string, std::string> > options_t;
	options_t supplied_options;

	// for now, get LLSD to iterator over form elements
	LLSD form_sd = form->asLLSD();

	S32 option_index = 0;
	for (LLSD::array_const_iterator it = form_sd.beginArray(); it != form_sd.endArray(); ++it)
	{
		std::string type = (*it)["type"].asString();
		if (type == "button")
		{
			if((*it)["default"])
			{
				mDefaultOption = option_index;
			}

			supplied_options.push_back(std::make_pair((*it)["name"].asString(), (*it)["text"].asString()));

			ButtonData data;
			if (option_index == mNotification->getURLOption())
			{
				data.mURL = mNotification->getURL();
				data.mURLExternal = mNotification->getURLOpenExternally();
			}

			mButtonData.push_back(data);
			option_index++;
		}
		else if (type == "text")
		{
			defaultText = (*it)["default"].asBoolean();
			edit_text_contents = (*it)["value"].asString();
			edit_text_name = (*it)["name"].asString();
			edit_text_max_chars = (*it)["max_length_chars"].asInteger();
		}
		else if (type == "password")
		{
			defaultText = (*it)["default"].asBoolean();
			edit_text_contents = (*it)["value"].asString();
			edit_text_name = (*it)["name"].asString();
			is_password = true;
		}
	}

	// Buttons
	options_t options;
	if (supplied_options.empty())
	{
		options.push_back(std::make_pair(std::string("close"), LLNotifications::instance().getGlobalString("implicitclosebutton")));

		// add data for ok button.
		ButtonData ok_button;
		mButtonData.push_back(ok_button);
		mDefaultOption = 0;
	}
	else
	{
		options = supplied_options;
	}

	S32 num_options = options.size();

	// Calc total width of buttons
	S32 button_width = 0;
	S32 sp = font->getWidth(std::string("OO"));
	for( S32 i = 0; i < num_options; i++ )
	{
		S32 w = S32(font->getWidth( options[i].second ) + 0.99f) + sp + 2 * LLBUTTON_H_PAD;
		button_width = llmax( w, button_width );
	}
	S32 btn_total_width = button_width;
	if( num_options > 1 )
	{
		btn_total_width = (num_options * button_width) + ((num_options - 1) * BTN_HPAD);
	}

	// Message: create text box using raw string, as text has been structure deliberately
	// Use size of created text box to generate dialog box size
	std::string msg = mNotification->getMessage();
	LL_WARNS() << "Alert: " << msg << LL_ENDL;
	LLTextBox::Params params;
	params.name("Alert message");
	params.font(font);
	params.tab_stop(false);
	params.wrap(true);
	params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP);
	params.allow_scroll(true);
	params.force_urls_external(mNotification->getForceUrlsExternal());

	LLTextBox * msg_box = LLUICtrlFactory::create<LLTextBox> (params);
	// Compute max allowable height for the dialog text, so we can allocate
	// space before wrapping the text to fit.
	S32 max_allowed_msg_height =
			gFloaterView->getRect().getHeight()
			- LINE_HEIGHT			// title bar
			- 3*VPAD - BTN_HEIGHT;
	// reshape to calculate real text width and height
	msg_box->reshape( MAX_ALLOWED_MSG_WIDTH, max_allowed_msg_height );

	if ("GroupLimitInfo" == mNotification->getName() || "GroupLimitInfoPlus" == mNotification->getName())
	{
		msg_box->setSkipLinkUnderline(true);
	}
	msg_box->setValue(msg);

	S32 pixel_width = msg_box->getTextPixelWidth();
	S32 pixel_height = msg_box->getTextPixelHeight();

	// We should use some space to prevent set textbox's scroller visible when it is unnecessary.
	msg_box->reshape( llmin(MAX_ALLOWED_MSG_WIDTH,pixel_width + 2 * msg_box->getHPad() + HPAD),
		llmin(max_allowed_msg_height,pixel_height + 2 * msg_box->getVPad())  ) ;

	const LLRect& text_rect = msg_box->getRect();
	S32 dialog_width = llmax( btn_total_width, text_rect.getWidth() ) + 2 * HPAD;
	S32 dialog_height = text_rect.getHeight() + 3 * VPAD + BTN_HEIGHT;

	if (hasTitleBar())
	{
		dialog_height += LINE_HEIGHT; // room for title bar
	}

	// it's ok for the edit text body to be empty, but we want the name to exist if we're going to draw it
	if (!edit_text_name.empty())
	{
		dialog_height += EDITOR_HEIGHT + VPAD;
		dialog_width = llmax(dialog_width, (S32)(font->getWidth( edit_text_contents ) + 0.99f));
	}

	if (mCaution)
	{
		// Make room for the caution icon.
		dialog_width += 32 + HPAD;
	}

	LLToastPanel::reshape( dialog_width, dialog_height, FALSE );

	S32 msg_y = LLToastPanel::getRect().getHeight() - VPAD;
	S32 msg_x = HPAD;
	if (hasTitleBar())
	{
		msg_y -= LINE_HEIGHT; // room for title
	}

	static LLUIColor alert_caution_text_color = LLUIColorTable::instance().getColor("AlertCautionTextColor");
	if (mCaution)
	{
		LLIconCtrl* icon = LLUICtrlFactory::getInstance()->createFromFile<LLIconCtrl>("alert_icon.xml", this, LLPanel::child_registry_t::instance());
		if(icon)
		{
			icon->setRect(LLRect(msg_x, msg_y, msg_x+32, msg_y-32));
			LLToastPanel::addChild(icon);
		}

		msg_x += 32 + HPAD;
		msg_box->setColor( alert_caution_text_color );
	}

	LLRect rect;
	rect.setLeftTopAndSize( msg_x, msg_y, text_rect.getWidth(), text_rect.getHeight() );
	msg_box->setRect( rect );
	LLToastPanel::addChild(msg_box);

	// (Optional) Edit Box
	if (!edit_text_name.empty())
	{
		S32 y = VPAD + BTN_HEIGHT + VPAD/2;
		mLineEditor = LLUICtrlFactory::getInstance()->createFromFile<LLLineEditor>("alert_line_editor.xml", this, LLPanel::child_registry_t::instance());

		if (mLineEditor)
		{
			LLRect leditor_rect = LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y);
			mLineEditor->setName(edit_text_name);
			mLineEditor->reshape(leditor_rect.getWidth(), leditor_rect.getHeight());
			mLineEditor->setRect(leditor_rect);
			mLineEditor->setMaxTextChars(edit_text_max_chars);
			mLineEditor->setText(edit_text_contents);

			std::string notif_name = mNotification->getName();
			if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name))
			{
				mLineEditor->setPrevalidate(&LLTextValidate::validateASCII);
			}

			// decrease limit of line editor of teleport offer dialog to avoid truncation of
			// location URL in invitation message, see EXT-6891
			if ("OfferTeleport" == notif_name)
			{
				mLineEditor->setMaxTextLength(gSavedSettings.getS32(
						"teleport_offer_invitation_max_length"));
			}
			else
			{
				mLineEditor->setMaxTextLength(STD_STRING_STR_LEN - 1);
			}

			LLToastPanel::addChild(mLineEditor);

			mLineEditor->setDrawAsterixes(is_password);

			setEditTextArgs(notification->getSubstitutions());

			mLineEditor->setFollowsLeft();
			mLineEditor->setFollowsRight();

			// find form text input field
			LLSD form_text;
			for (LLSD::array_const_iterator it = form_sd.beginArray(); it != form_sd.endArray(); ++it)
			{
				std::string type = (*it)["type"].asString();
				if (type == "text")
				{
					form_text = (*it);
				}
			}

			// if form text input field has width attribute
			if (form_text.has("width"))
			{
				// adjust floater width to fit line editor
				S32 editor_width = form_text["width"];
				LLRect editor_rect =  mLineEditor->getRect();
				U32 width_delta = editor_width  - editor_rect.getWidth();
				LLRect toast_rect = getRect();
				reshape(toast_rect.getWidth() +  width_delta, toast_rect.getHeight());
			}
		}
	}

	// Buttons
	S32 button_left = (LLToastPanel::getRect().getWidth() - btn_total_width) / 2;

	for( S32 i = 0; i < num_options; i++ )
	{
		LLRect button_rect;

		LLButton* btn = LLUICtrlFactory::getInstance()->createFromFile<LLButton>("alert_button.xml", this, LLPanel::child_registry_t::instance());
		if(btn)
		{
			btn->setName(options[i].first);
			btn->setRect(button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT ));
			btn->setLabel(options[i].second);
			btn->setFont(font);

			btn->setClickedCallback(boost::bind(&LLToastAlertPanel::onButtonPressed, this, _2, i));

			mButtonData[i].mButton = btn;

			LLToastPanel::addChild(btn);

			if( i == mDefaultOption )
			{
				btn->setFocus(TRUE);
			}
		}
		button_left += button_width + BTN_HPAD;
	}

	if(defaultText)
	{
		if(mLineEditor)
		{
			mLineEditor->setFocus(TRUE);
		}
	}

	setCheckBoxes(HPAD, VPAD);

	// *TODO: check necessity of this code
	//gFloaterView->adjustToFitScreen(this, FALSE);
	if (mLineEditor)
	{
		mLineEditor->selectAll();
		mLineEditor->setFocus(TRUE);
	}
	if(mDefaultOption >= 0)
	{
		// delay before enabling default button
		mDefaultBtnTimer.start();
		mDefaultBtnTimer.setTimerExpirySec(DEFAULT_BUTTON_DELAY);
	}

	LLTransientFloaterMgr::instance().addControlView(
			LLTransientFloaterMgr::GLOBAL, this);
}

void LLToastAlertPanel::setVisible( BOOL visible )
{
	// only make the "ding" sound if it's newly visible
	// <FS:PP> FIRE-4322: The "bing" system sound missing
	// if( visible && !LLToastPanel::getVisible() )
	LLToastPanel::setVisible( visible );
	if (visible && !LLApp::isExiting())
	// </FS:PP>
	{
		make_ui_sound("UISndAlert");
	}

	// <FS:PP> Commented out and moved up, for FIRE-4322 patch
	// LLToastPanel::setVisible( visible );

}

LLToastAlertPanel::~LLToastAlertPanel()
{
	LLTransientFloaterMgr::instance().removeControlView(
			LLTransientFloaterMgr::GLOBAL, this);

	// EXP-1822
	// return focus to the previously focused view if the viewer is not exiting
	if (mPreviouslyFocusedView.get() && !LLApp::isExiting())
	{
        LLView* current_selection = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus());
        while(current_selection)
        {
            // <FS:Ansariel> FIRE-6651: Modal alert toasts don't restore focus properly
            //if (current_selection->isFocusRoot())
            if (current_selection->isFocusRoot() && (!dynamic_cast<LLFloater*>(current_selection) || !dynamic_cast<LLFloater*>(current_selection)->getHost()))
            // </FS:Ansariel>
            {
                break;
            }
            current_selection = current_selection->getParent();
        }
        if (current_selection)
        {
            // If the focus moved to some other view though, move the focus there
            current_selection->setFocus(TRUE);
        }
        else
        {
            mPreviouslyFocusedView.get()->setFocus(TRUE);
        }
	}
}

BOOL LLToastAlertPanel::hasTitleBar() const
{
	// *TODO: check necessity of this code
	/*
	return (getCurrentTitle() != "" && getCurrentTitle() != " ")	// has title
			|| isMinimizeable()
			|| isCloseable();
	*/
	return false;
}

BOOL LLToastAlertPanel::handleKeyHere(KEY key, MASK mask )
{
	if( KEY_RETURN == key && mask == MASK_NONE )
	{
		LLButton* defaultBtn = getDefaultButton();
		if(defaultBtn && defaultBtn->getVisible() && defaultBtn->getEnabled())
		{
			// If we have a default button, click it when return is pressed
			defaultBtn->onCommit();
		}
		return TRUE;
	}
	else if (KEY_RIGHT == key)
	{
		LLToastPanel::focusNextItem(FALSE);
		return TRUE;
	}
	else if (KEY_LEFT == key)
	{
		LLToastPanel::focusPrevItem(FALSE);
		return TRUE;
	}
	else if (KEY_TAB == key && mask == MASK_NONE)
	{
		LLToastPanel::focusNextItem(FALSE);
		return TRUE;
	}
	else if (KEY_TAB == key && mask == MASK_SHIFT)
	{
		LLToastPanel::focusPrevItem(FALSE);
		return TRUE;
	}
	else
	{
		return TRUE;
	}
}

// virtual
void LLToastAlertPanel::draw()
{
	// if the default button timer has just expired, activate the default button
	if(mDefaultBtnTimer.hasExpired() && mDefaultBtnTimer.getStarted())
	{
		mDefaultBtnTimer.stop();  // prevent this block from being run more than once
		LLToastPanel::setDefaultBtn(mButtonData[mDefaultOption].mButton);
	}

	static LLUIColor shadow_color = LLUIColorTable::instance().getColor("ColorDropShadow");
	static LLUICachedControl<S32> shadow_lines ("DropShadowFloater", 5);

	gl_drop_shadow( 0, LLToastPanel::getRect().getHeight(), LLToastPanel::getRect().getWidth(), 0,
		shadow_color, shadow_lines);

	LLToastPanel::draw();
}

void LLToastAlertPanel::setEditTextArgs(const LLSD& edit_args)
{
	if (mLineEditor)
	{
		std::string msg = mLineEditor->getText();
		mLineEditor->setText(msg);
	}
	else
	{
		LL_WARNS() << "LLToastAlertPanel::setEditTextArgs called on dialog with no line editor" << LL_ENDL;
	}
}

void LLToastAlertPanel::onButtonPressed( const LLSD& data, S32 button )
{
	ButtonData* button_data = &mButtonData[button];

	LLSD response = mNotification->getResponseTemplate();
	if (mLineEditor)
	{
		response[mLineEditor->getName()] = mLineEditor->getValue();
	}
	response[button_data->mButton->getName()] = true;

	// If we declared a URL and chose the URL option, go to the url
	if (!button_data->mURL.empty())
	{
		if (button_data->mURLExternal)
		{
			LLWeb::loadURLExternal(button_data->mURL);
		}
		else
		{
			LLWeb::loadURL(button_data->mURL);
		}
	}

	mNotification->respond(response); // new notification reponse
}

max_stars_repo_name: SaladDais/LLUDP-Encryption

max_issues_repo_name: SaladDais/LLUDP-Encryption

max_forks_repo_name: SaladDais/LLUDP-Encryption