<commit_before>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2017 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2015 - 2017)
//   Rene Milk       (2016 - 2017)
//   Tobias Leibner  (2016)

#ifndef DUNE_GDT_TEST_STATIONARY_EOCSTUDY_HH
#define DUNE_GDT_TEST_STATIONARY_EOCSTUDY_HH

#include <dune/xt/common/convergence-study.hh>
#include <dune/xt/common/exceptions.hh>
#include <dune/xt/grid/type_traits.hh>

#include <dune/gdt/discretizations/default.hh>
#include <dune/gdt/discretizations/interfaces.hh>
#include <dune/gdt/prolongations.hh>

#include "stationary-testcase.hh"

namespace Dune {
namespace GDT {
namespace Test {

template <class TestCaseImp, class DiscretizerImp>
class StationaryEocStudy : public XT::Common::ConvergenceStudy
{
  typedef XT::Common::ConvergenceStudy BaseType;

protected:
  typedef TestCaseImp TestCaseType;
  typedef DiscretizerImp Discretizer;
  typedef typename Discretizer::DiscretizationType DiscretizationType;
  typedef typename TestCaseType::GridType GridType;
  typedef typename Discretizer::ProblemType ProblemType;
  typedef typename DiscretizationType::VectorType VectorType;
  typedef typename DiscretizationType::AnsatzSpaceType SpaceType;
  typedef GDT::DiscreteFunction<SpaceType, VectorType> DiscreteFunctionType;
  typedef GDT::ConstDiscreteFunction<SpaceType, VectorType> ConstDiscreteFunctionType;

  typedef typename TestCaseType::FunctionType FunctionType;
  typedef typename TestCaseType::LevelGridLayerType GridLayerType;

public:
  StationaryEocStudy(TestCaseType& test_case,
                     const std::vector<std::string> only_these_norms = {},
                     const std::string visualize_prefix = "")
    : BaseType(only_these_norms)
    , test_case_(test_case)
    , current_refinement_(0)
    , last_computed_refinement_(std::numeric_limits<size_t>::max())
    , grid_widths_(test_case.num_refinements() + 1, -1.0)
    , time_to_solution_(0)
    , reference_solution_computed_(false)
    , current_discretization_(nullptr)
    , current_solution_vector_on_level_(nullptr)
    , reference_discretization_(nullptr)
    , reference_solution_vector_(nullptr)
    , current_solution_vector_(nullptr)
    , visualize_prefix_(visualize_prefix)
    , current_num_DoFs_(0)
  {
  }

  virtual ~StationaryEocStudy() = default;

  virtual size_t num_refinements() const override final
  {
    return test_case_.num_refinements();
  }

  virtual std::vector<std::string> provided_norms() const override final
  {
    std::vector<std::string> ret = available_norms();
    for (auto estimator : available_estimators()) {
      if (is_norm(estimator))
        DUNE_THROW(XT::Common::Exceptions::internal_error,
                   "We do not want to handle the case that norms and estimators have the same name!");
      ret.push_back(estimator);
    }
    return ret;
  } // ... provided_norms(...)

  virtual double norm_reference_solution(const std::string type) override final
  {
    if (!is_norm(type))
      DUNE_THROW(XT::Common::Exceptions::you_are_using_this_wrong,
                 "Do not call norm_reference_solution() for an estimator!\n"
                     << "type: "
                     << type
                     << "\n");
    if (test_case_.provides_exact_solution()) {
      // visualize
      if (!visualize_prefix_.empty()) {
        test_case_.exact_solution().visualize(test_case_.reference_grid_layer(), visualize_prefix_ + "_exact_solution");
      }
      return compute_norm(test_case_.reference_grid_layer(), test_case_.exact_solution(), type);
    } else {
      compute_reference_solution();
      assert(reference_discretization_);
      assert(reference_solution_vector_);
      const ConstDiscreteFunctionType reference_solution(
          reference_discretization_->ansatz_space(), *reference_solution_vector_, "reference solution");
      return compute_norm(test_case_.reference_grid_layer(), reference_solution, type);
    }
  } // ... norm_reference_solution(...)

  virtual size_t current_num_DoFs() override final
  {
    if (current_refinement_ != last_computed_refinement_) {
      assert(current_refinement_ <= num_refinements());
      current_num_DoFs_ =
          Discretizer::discretize(test_case_, test_case_.problem(), test_case_.level_of(current_refinement_))
              .ansatz_space()
              .mapper()
              .size();
    }
    return current_num_DoFs_;
  } // ... current_num_DoFs(...)

  virtual size_t current_grid_size() const override final
  {
    assert(current_refinement_ <= num_refinements());
    return test_case_.level_view(test_case_.level_of(current_refinement_)).indexSet().size(0);
  } // ... current_grid_size(...)

  virtual double current_grid_width() override final
  {
    assert(current_refinement_ <= num_refinements());
    if (grid_widths_[current_refinement_] < 0.0) {
      const int level = test_case_.level_of(current_refinement_);
      const auto grid_layer = test_case_.template level<XT::Grid::Backends::view>(level);
      XT::Grid::Dimensions<GridLayerType> dimensions(grid_layer);
      grid_widths_[current_refinement_] = dimensions.entity_width.max();
      assert(grid_widths_[current_refinement_] > 0.0);
    }
    return grid_widths_[current_refinement_];
  } // ... current_grid_width(...)

  virtual double compute_on_current_refinement() override final
  {
    if (current_refinement_ != last_computed_refinement_) {
      assert(current_refinement_ <= num_refinements());
      // compute solution
      Timer timer;
      current_discretization_ = XT::Common::make_unique<DiscretizationType>(
          Discretizer::discretize(test_case_, test_case_.problem(), test_case_.level_of(current_refinement_)));
      current_solution_vector_on_level_ = XT::Common::make_unique<VectorType>(current_discretization_->solve());
      time_to_solution_ = timer.elapsed();
      const ConstDiscreteFunctionType current_refinement_solution(
          current_discretization_->ansatz_space(), *current_solution_vector_on_level_, "solution on current level");
      // prolong to reference grid part
      compute_reference_solution();
      assert(reference_discretization_);
      if (!current_solution_vector_)
        current_solution_vector_ = XT::Common::make_unique<VectorType>(reference_discretization_->create_vector());
      DiscreteFunctionType reference_refinement_solution(
          reference_discretization_->ansatz_space(), *current_solution_vector_, "solution on reference grid part");
      prolong(current_refinement_solution, reference_refinement_solution);
      last_computed_refinement_ = current_refinement_;
      // visualize
      if (!visualize_prefix_.empty()) {
        this->test_case_.problem().visualize(current_discretization_->ansatz_space().grid_layer(),
                                             visualize_prefix_ + "_problem_"
                                                 + Dune::XT::Common::to_string(current_refinement_));
        current_refinement_solution.visualize(visualize_prefix_ + "_solution_"
                                              + Dune::XT::Common::to_string(current_refinement_));
      }
    }
    return time_to_solution_;
  } // ... compute_on_current_refinement(...)

  virtual double current_error_norm(const std::string type) override final
  {
    // get current solution
    assert(current_refinement_ <= num_refinements());
    compute_on_current_refinement();
    assert(last_computed_refinement_ == current_refinement_);
    if (is_norm(type)) {
      assert(current_solution_vector_);
      compute_reference_solution();
      assert(reference_discretization_);
      const ConstDiscreteFunctionType current_solution(
          reference_discretization_->ansatz_space(), *current_solution_vector_, "current solution");
      // compute error
      if (test_case_.provides_exact_solution()) {
        return compute_norm(test_case_.reference_grid_layer(), test_case_.exact_solution() - current_solution, type);
      } else {
        // get reference solution
        compute_reference_solution();
        assert(reference_discretization_);
        assert(reference_solution_vector_);
        const ConstDiscreteFunctionType reference_solution(
            reference_discretization_->ansatz_space(), *reference_solution_vector_, "reference solution");
        return compute_norm(test_case_.reference_grid_layer(), reference_solution - current_solution, type);
      }
    } else {
      assert(current_solution_vector_on_level_);
      return estimate(*current_solution_vector_on_level_, type);
    }
  } // ... current_error_norm(...)

  virtual void refine() override final
  {
    if (current_refinement_ <= num_refinements())
      ++current_refinement_;
  }

  std::map<std::string, std::vector<double>> run(std::ostream& out, const bool print_timings = true)
  {
    return BaseType::run(true, out, print_timings);
  }

protected:
  void compute_reference_solution()
  {
    if (!reference_solution_computed_) {
      reference_discretization_ = XT::Common::make_unique<DiscretizationType>(
          Discretizer::discretize(test_case_, test_case_.problem(), test_case_.reference_level()));
      reference_solution_vector_ = XT::Common::make_unique<VectorType>(reference_discretization_->solve());
      reference_solution_computed_ = true;
      // visualize
      if (!visualize_prefix_.empty()) {
        this->test_case_.problem().visualize(reference_discretization_->ansatz_space().grid_layer(),
                                             visualize_prefix_ + "_problem_reference");
        ConstDiscreteFunctionType(
            reference_discretization_->ansatz_space(), *reference_solution_vector_, "reference solution")
            .visualize(visualize_prefix_ + "_reference_solution");
      }
    }
  } // ... compute_reference_solution()

  bool is_norm(const std::string type) const
  {
    const auto norms = available_norms();
    return std::find(norms.begin(), norms.end(), type) != norms.end();
  }

  virtual std::vector<std::string> available_norms() const = 0;

  virtual std::vector<std::string> available_estimators() const = 0;

  virtual double estimate(const VectorType& vector, const std::string type) = 0;

  virtual double
  compute_norm(const GridLayerType& grid_layer, const FunctionType& function, const std::string type) = 0;

  TestCaseType& test_case_;
  size_t current_refinement_;
  size_t last_computed_refinement_;
  std::vector<double> grid_widths_;
  double time_to_solution_;
  bool reference_solution_computed_;
  std::unique_ptr<DiscretizationType> current_discretization_;
  std::unique_ptr<VectorType> current_solution_vector_on_level_;
  std::unique_ptr<DiscretizationType> reference_discretization_;
  std::unique_ptr<VectorType> reference_solution_vector_;
  std::unique_ptr<VectorType> current_solution_vector_;
  const std::string visualize_prefix_;
  size_t current_num_DoFs_;
}; // class StationaryEocStudy

} // namespace Test
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_TEST_STATIONARY_EOCSTUDY_HH
<commit_msg>[test.stationary-eocstudy] fix deprecated grid layer handling<commit_after>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2017 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2015 - 2017)
//   Rene Milk       (2016 - 2017)
//   Tobias Leibner  (2016)

#ifndef DUNE_GDT_TEST_STATIONARY_EOCSTUDY_HH
#define DUNE_GDT_TEST_STATIONARY_EOCSTUDY_HH

#include <dune/xt/common/convergence-study.hh>
#include <dune/xt/common/exceptions.hh>
#include <dune/xt/grid/type_traits.hh>

#include <dune/gdt/discretizations/default.hh>
#include <dune/gdt/discretizations/interfaces.hh>
#include <dune/gdt/prolongations.hh>

#include "stationary-testcase.hh"

namespace Dune {
namespace GDT {
namespace Test {

template <class TestCaseImp, class DiscretizerImp>
class StationaryEocStudy : public XT::Common::ConvergenceStudy
{
  typedef XT::Common::ConvergenceStudy BaseType;

protected:
  typedef TestCaseImp TestCaseType;
  typedef DiscretizerImp Discretizer;
  typedef typename Discretizer::DiscretizationType DiscretizationType;
  typedef typename TestCaseType::GridType GridType;
  typedef typename Discretizer::ProblemType ProblemType;
  typedef typename DiscretizationType::VectorType VectorType;
  typedef typename DiscretizationType::AnsatzSpaceType SpaceType;
  typedef GDT::DiscreteFunction<SpaceType, VectorType> DiscreteFunctionType;
  typedef GDT::ConstDiscreteFunction<SpaceType, VectorType> ConstDiscreteFunctionType;

  typedef typename TestCaseType::FunctionType FunctionType;
  typedef typename SpaceType::GridLayerType GridLayerType;

public:
  StationaryEocStudy(TestCaseType& test_case,
                     const std::vector<std::string> only_these_norms = {},
                     const std::string visualize_prefix = "")
    : BaseType(only_these_norms)
    , test_case_(test_case)
    , current_refinement_(0)
    , last_computed_refinement_(std::numeric_limits<size_t>::max())
    , grid_widths_(test_case.num_refinements() + 1, -1.0)
    , time_to_solution_(0)
    , reference_solution_computed_(false)
    , current_discretization_(nullptr)
    , current_solution_vector_on_level_(nullptr)
    , reference_discretization_(nullptr)
    , reference_solution_vector_(nullptr)
    , current_solution_vector_(nullptr)
    , visualize_prefix_(visualize_prefix)
    , current_num_DoFs_(0)
  {
  }

  virtual ~StationaryEocStudy() = default;

  virtual size_t num_refinements() const override final
  {
    return test_case_.num_refinements();
  }

  virtual std::vector<std::string> provided_norms() const override final
  {
    std::vector<std::string> ret = available_norms();
    for (auto estimator : available_estimators()) {
      if (is_norm(estimator))
        DUNE_THROW(XT::Common::Exceptions::internal_error,
                   "We do not want to handle the case that norms and estimators have the same name!");
      ret.push_back(estimator);
    }
    return ret;
  } // ... provided_norms(...)

  virtual double norm_reference_solution(const std::string type) override final
  {
    if (!is_norm(type))
      DUNE_THROW(XT::Common::Exceptions::you_are_using_this_wrong,
                 "Do not call norm_reference_solution() for an estimator!\n"
                     << "type: "
                     << type
                     << "\n");
    if (test_case_.provides_exact_solution()) {
      // visualize
      if (!visualize_prefix_.empty()) {
        test_case_.exact_solution().visualize(test_case_.template reference_layer<SpaceType::layer_backend>(),
                                              visualize_prefix_ + "_exact_solution");
      }
      return compute_norm(
          test_case_.template reference_layer<SpaceType::layer_backend>(), test_case_.exact_solution(), type);
    } else {
      compute_reference_solution();
      assert(reference_discretization_);
      assert(reference_solution_vector_);
      const ConstDiscreteFunctionType reference_solution(
          reference_discretization_->ansatz_space(), *reference_solution_vector_, "reference solution");
      return compute_norm(test_case_.template reference_layer<SpaceType::layer_backend>(), reference_solution, type);
    }
  } // ... norm_reference_solution(...)

  virtual size_t current_num_DoFs() override final
  {
    if (current_refinement_ != last_computed_refinement_) {
      assert(current_refinement_ <= num_refinements());
      current_num_DoFs_ =
          Discretizer::discretize(test_case_, test_case_.problem(), test_case_.level_of(current_refinement_))
              .ansatz_space()
              .mapper()
              .size();
    }
    return current_num_DoFs_;
  } // ... current_num_DoFs(...)

  virtual size_t current_grid_size() const override final
  {
    assert(current_refinement_ <= num_refinements());
    return test_case_.level_view(test_case_.level_of(current_refinement_)).indexSet().size(0);
  } // ... current_grid_size(...)

  virtual double current_grid_width() override final
  {
    assert(current_refinement_ <= num_refinements());
    if (grid_widths_[current_refinement_] < 0.0) {
      const int level = test_case_.level_of(current_refinement_);
      const auto grid_layer = test_case_.template level<XT::Grid::Backends::view>(level);
      grid_widths_[current_refinement_] = XT::Grid::dimensions(grid_layer).entity_width.max();
      assert(grid_widths_[current_refinement_] > 0.0);
    }
    return grid_widths_[current_refinement_];
  } // ... current_grid_width(...)

  virtual double compute_on_current_refinement() override final
  {
    if (current_refinement_ != last_computed_refinement_) {
      assert(current_refinement_ <= num_refinements());
      // compute solution
      Timer timer;
      current_discretization_ = XT::Common::make_unique<DiscretizationType>(
          Discretizer::discretize(test_case_, test_case_.problem(), test_case_.level_of(current_refinement_)));
      current_solution_vector_on_level_ = XT::Common::make_unique<VectorType>(current_discretization_->solve());
      time_to_solution_ = timer.elapsed();
      const ConstDiscreteFunctionType current_refinement_solution(
          current_discretization_->ansatz_space(), *current_solution_vector_on_level_, "solution on current level");
      // prolong to reference grid part
      compute_reference_solution();
      assert(reference_discretization_);
      if (!current_solution_vector_)
        current_solution_vector_ = XT::Common::make_unique<VectorType>(reference_discretization_->create_vector());
      DiscreteFunctionType reference_refinement_solution(
          reference_discretization_->ansatz_space(), *current_solution_vector_, "solution on reference grid part");
      prolong(current_refinement_solution, reference_refinement_solution);
      last_computed_refinement_ = current_refinement_;
      // visualize
      if (!visualize_prefix_.empty()) {
        this->test_case_.problem().visualize(test_case_.level_view(test_case_.level_of(current_refinement_)),
                                             visualize_prefix_ + "_problem_"
                                                 + Dune::XT::Common::to_string(current_refinement_));
        current_refinement_solution.visualize(visualize_prefix_ + "_solution_"
                                              + Dune::XT::Common::to_string(current_refinement_));
      }
    }
    return time_to_solution_;
  } // ... compute_on_current_refinement(...)

  virtual double current_error_norm(const std::string type) override final
  {
    // get current solution
    assert(current_refinement_ <= num_refinements());
    compute_on_current_refinement();
    assert(last_computed_refinement_ == current_refinement_);
    if (is_norm(type)) {
      assert(current_solution_vector_);
      compute_reference_solution();
      assert(reference_discretization_);
      const ConstDiscreteFunctionType current_solution(
          reference_discretization_->ansatz_space(), *current_solution_vector_, "current solution");
      // compute error
      if (test_case_.provides_exact_solution()) {
        return compute_norm(test_case_.template reference_layer<SpaceType::layer_backend>(),
                            test_case_.exact_solution() - current_solution,
                            type);
      } else {
        // get reference solution
        compute_reference_solution();
        assert(reference_discretization_);
        assert(reference_solution_vector_);
        const ConstDiscreteFunctionType reference_solution(
            reference_discretization_->ansatz_space(), *reference_solution_vector_, "reference solution");
        return compute_norm(test_case_.template reference_layer<SpaceType::layer_backend>(),
                            reference_solution - current_solution,
                            type);
      }
    } else {
      assert(current_solution_vector_on_level_);
      return estimate(*current_solution_vector_on_level_, type);
    }
  } // ... current_error_norm(...)

  virtual void refine() override final
  {
    if (current_refinement_ <= num_refinements())
      ++current_refinement_;
  }

  std::map<std::string, std::vector<double>> run(std::ostream& out, const bool print_timings = true)
  {
    return BaseType::run(true, out, print_timings);
  }

protected:
  void compute_reference_solution()
  {
    if (!reference_solution_computed_) {
      reference_discretization_ = XT::Common::make_unique<DiscretizationType>(
          Discretizer::discretize(test_case_, test_case_.problem(), test_case_.reference_level()));
      reference_solution_vector_ = XT::Common::make_unique<VectorType>(reference_discretization_->solve());
      reference_solution_computed_ = true;
      // visualize
      if (!visualize_prefix_.empty()) {
        this->test_case_.problem().visualize(test_case_.reference_grid_view(),
                                             visualize_prefix_ + "_problem_reference");
        ConstDiscreteFunctionType(
            reference_discretization_->ansatz_space(), *reference_solution_vector_, "reference solution")
            .visualize(visualize_prefix_ + "_reference_solution");
      }
    }
  } // ... compute_reference_solution()

  bool is_norm(const std::string type) const
  {
    const auto norms = available_norms();
    return std::find(norms.begin(), norms.end(), type) != norms.end();
  }

  virtual std::vector<std::string> available_norms() const = 0;

  virtual std::vector<std::string> available_estimators() const = 0;

  virtual double estimate(const VectorType& vector, const std::string type) = 0;

  virtual double
  compute_norm(const GridLayerType& grid_layer, const FunctionType& function, const std::string type) = 0;

  TestCaseType& test_case_;
  size_t current_refinement_;
  size_t last_computed_refinement_;
  std::vector<double> grid_widths_;
  double time_to_solution_;
  bool reference_solution_computed_;
  std::unique_ptr<DiscretizationType> current_discretization_;
  std::unique_ptr<VectorType> current_solution_vector_on_level_;
  std::unique_ptr<DiscretizationType> reference_discretization_;
  std::unique_ptr<VectorType> reference_solution_vector_;
  std::unique_ptr<VectorType> current_solution_vector_;
  const std::string visualize_prefix_;
  size_t current_num_DoFs_;
}; // class StationaryEocStudy

} // namespace Test
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_TEST_STATIONARY_EOCSTUDY_HH
<|endoftext|>


<commit_before>#include "level.hpp"

using namespace engine;

void Level::load(){
  for(auto game_object : objects){
    std::cout << "Loading " << game_object->name << std::endl;
    game_object->load();
    for(auto hit : game_object->get_hitboxes()){
      hit->initialize();
    }
  }
}

void Level::free(){
  for(auto game_object : objects){
    std::cout << "Freeing" << game_object->name << std::endl;
    game_object->free();
  }
  EventHandler::listeners.clear();
}

void Level::draw(){
  for(auto game_object : objects){
    if(game_object->is_active()){
      game_object->draw();
    }
  }
}
<commit_msg>Fix wrong animation of boss arm<commit_after>#include "level.hpp"
#include <iostream>

using namespace engine;

void Level::load(){
  for(auto game_object : objects){
    std::cout << "Loading " << game_object->name << std::endl;
    game_object->load();
    for(auto hit : game_object->get_hitboxes()){
      hit->initialize();
    }
  }
}

void Level::free(){
  for(auto game_object : objects){
    std::cout << "Freeing" << game_object->name << std::endl;
    game_object->free();
  }
  EventHandler::listeners.clear();
}

void Level::draw(){
  for(auto game_object : objects){
    if(game_object->is_active()){
      if(game_object->name == "arm_left"){
        game_object->set_actual_animation(game_object->animations["left_arm"]);
      }

      game_object->draw();
    }
  }
}
<|endoftext|>


<commit_before>/*
   fskit: a library for creating multi-threaded in-RAM filesystems
   Copyright (C) 2014  Jude Nelson

   This program is dual-licensed: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License version 3 or later as
   published by the Free Software Foundation. For the terms of this
   license, see LICENSE.LGPLv3+ or <http://www.gnu.org/licenses/>.

   You are free to use this program under the terms of the GNU Lesser General
   Public License, 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.

   Alternatively, you are free to use this program under the terms of the
   Internet Software Consortium License, but WITHOUT ANY WARRANTY; without
   even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   For the terms of this license, see LICENSE.ISC or
   <http://www.isc.org/downloads/software-support-policy/isc-license/>.
*/

#include <fskit/sync.h>
#include <fskit/route.h>

static int fskit_do_user_sync( struct fskit_core* core, char const* path, struct fskit_entry* fent ) {

   int rc = 0;
   int cbrc = 0;

   struct fskit_route_dispatch_args dargs;

   fskit_route_sync_args( &dargs );

   rc = fskit_route_call_sync( core, path, fent, &dargs, &cbrc );

   if( rc == -EPERM || rc == -ENOSYS ) {
      // no stat defined
      return 0;
   }

   return cbrc;
}

// sync a file handle
// basically, just call the user route, but write-lock the entry
int fskit_fsync( struct fskit_core* core, struct fskit_file_handle* fh ) {

   fskit_file_handle_rlock( fh );
   fskit_entry_wlock( fh->fent );

   int rc = fskit_do_user_sync( core, fh->path, fh->fent );

   fskit_entry_unlock( fh->fent );
   fskit_file_handle_unlock( fh );

   return rc;
}
<commit_msg>Do *NOT* lock the inode when calling the user sync route--that's the route consistency discipline's job.<commit_after>/*
   fskit: a library for creating multi-threaded in-RAM filesystems
   Copyright (C) 2014  Jude Nelson

   This program is dual-licensed: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License version 3 or later as
   published by the Free Software Foundation. For the terms of this
   license, see LICENSE.LGPLv3+ or <http://www.gnu.org/licenses/>.

   You are free to use this program under the terms of the GNU Lesser General
   Public License, 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.

   Alternatively, you are free to use this program under the terms of the
   Internet Software Consortium License, but WITHOUT ANY WARRANTY; without
   even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   For the terms of this license, see LICENSE.ISC or
   <http://www.isc.org/downloads/software-support-policy/isc-license/>.
*/

#include <fskit/sync.h>
#include <fskit/route.h>
#include <fskit/path.h>

static int fskit_do_user_sync( struct fskit_core* core, char const* path, struct fskit_entry* fent ) {

   int rc = 0;
   int cbrc = 0;

   struct fskit_route_dispatch_args dargs;

   fskit_route_sync_args( &dargs );

   rc = fskit_route_call_sync( core, path, fent, &dargs, &cbrc );

   if( rc == -EPERM || rc == -ENOSYS ) {
      // no stat defined
      return 0;
   }

   return cbrc;
}

// sync a file handle
// basically, just call the user route
int fskit_fsync( struct fskit_core* core, struct fskit_file_handle* fh ) {

   fskit_file_handle_rlock( fh );

   int rc = fskit_do_user_sync( core, fh->path, fh->fent );

   fskit_file_handle_unlock( fh );

   return rc;
}
<|endoftext|>


<commit_before><commit_msg>Fix unblock code<commit_after><|endoftext|>


<commit_before>
/** \file entry_impl.cpp
 *
 * \brief Source file pertaining to EntryImpl class.
 *
 * \author Matthew Harvey
 * \date 04 July 2012.
 *
 * Copyright (c) 2012, Matthew Harvey. All rights reserved.
 */

#include "entry_impl.hpp"
#include "account.hpp"
#include "b_string.hpp"
#include "commodity.hpp"
#include "phatbooks_database_connection.hpp"
#include "b_string.hpp"
#include <sqloxx/database_connection.hpp>
#include <sqloxx/general_typedefs.hpp>
#include <sqloxx/handle.hpp>
#include <sqloxx/sql_statement.hpp>
#include <boost/shared_ptr.hpp>
#include <jewel/debug_log.hpp>
#include <jewel/decimal.hpp>
#include <jewel/optional.hpp>
#include <string>

using sqloxx::SQLStatement;
using boost::shared_ptr;
using jewel::clear;
using jewel::Decimal;
using jewel::value;
using std::string;

#ifdef DEBUG
	#include <iomanip>
	#include <iostream>
#endif

namespace phatbooks
{

void EntryImpl::setup_tables(PhatbooksDatabaseConnection& dbc)
{
	dbc.execute_sql
	(	"create table entries"
		"("
			"entry_id integer primary key autoincrement, "
			"journal_id not null references journals, "
			"comment text, "
			"account_id not null references accounts, "
			"amount integer not null, "
			"is_reconciled not null references booleans"
		");"
	);
	dbc.execute_sql
	(	"create index entry_journal_index on entries(journal_id); "
	);
	return;
}

EntryImpl::EntryImpl
(	IdentityMap& p_identity_map
):
	PersistentObject(p_identity_map),
	m_data(new EntryData)
{
}

EntryImpl::EntryImpl
(	IdentityMap& p_identity_map,
	Id p_id
):
	PersistentObject(p_identity_map, p_id),
	m_data(new EntryData)
{
}

EntryImpl::~EntryImpl()
{
	/* If m_data is a smart pointer, this is not required.
	delete m_data;
	m_data = 0;
	*/
}

void
EntryImpl::set_journal_id(Id p_journal_id)
{
	load();
	m_data->journal_id = p_journal_id;
	return;
}

void
EntryImpl::set_account(Account const& p_account)
{
	load();
	m_data->account = p_account;
	return;
}

void
EntryImpl::set_comment(BString const& p_comment)
{
	load();
	m_data->comment = p_comment;
	return;
}

void
EntryImpl::set_amount(Decimal const& p_amount)
{
	load();
	m_data->amount = p_amount;
	return;
}

void
EntryImpl::set_whether_reconciled(bool p_is_reconciled)
{
	load();
	m_data->is_reconciled = p_is_reconciled;
	return;
}

Account
EntryImpl::account()
{
	load();
	return value(m_data->account);
}

BString
EntryImpl::comment()
{
	load();
	return value(m_data->comment);
}

jewel::Decimal
EntryImpl::amount()
{
	load();
	return value(m_data->amount);
}

bool
EntryImpl::is_reconciled()
{
	load();
	return value(m_data->is_reconciled);
}

void
EntryImpl::swap(EntryImpl& rhs)
{
	swap_base_internals(rhs);
	using std::swap;
	swap(m_data, rhs.m_data);
	return;
}

EntryImpl::EntryImpl(EntryImpl const& rhs):
	PersistentObject(rhs),
	m_data(new EntryData(*(rhs.m_data)))
{
}

void
EntryImpl::do_load()
{
	EntryImpl temp(*this);
	SQLStatement statement
	(	database_connection(),
		"select account_id, comment, amount, journal_id, is_reconciled "
		" from entries where "
		"entry_id = :p"
	);
	statement.bind(":p", id());
	statement.step();
	Account const acct
	(	database_connection(),
		statement.extract<Account::Id>(0)
	);
	Decimal const amt
	(	statement.extract<Decimal::int_type>(2),
		acct.commodity().precision()
	);

	temp.m_data->account = acct;
	temp.m_data->comment = std8_to_bstring(statement.extract<string>(1));
	temp.m_data->amount = amt;
	temp.m_data->journal_id = statement.extract<Id>(3);
	temp.m_data->is_reconciled =
		static_cast<bool>(statement.extract<int>(4));

	swap(temp);
	return;
}

void
EntryImpl::process_saving_statement(SQLStatement& statement)
{
	statement.bind(":journal_id", value(m_data->journal_id));
	statement.bind(":comment", bstring_to_std8(value(m_data->comment)));
	statement.bind(":account_id", value(m_data->account).id());
	statement.bind(":amount", m_data->amount->intval());
	statement.bind
	(	":is_reconciled",
		static_cast<int>(value(m_data->is_reconciled))
	);
	statement.step_final();
	return;
}

void
EntryImpl::do_save_existing()
{
	PhatbooksDatabaseConnection::BalanceCacheAttorney::mark_as_stale
	(	database_connection(),
		account().id()
	);
	SQLStatement updater
	(	database_connection(),
		"update entries set "
		"journal_id = :journal_id, "
		"comment = :comment, "
		"account_id = :account_id, "
		"amount = :amount, "
		"is_reconciled = :is_reconciled "
		"where entry_id = :entry_id"
	);
	updater.bind(":entry_id", id());
	process_saving_statement(updater);
	return;
}

void
EntryImpl::do_save_new()
{
	PhatbooksDatabaseConnection::BalanceCacheAttorney::mark_as_stale
	(	database_connection(),
		account().id()
	);
	SQLStatement inserter
	(	database_connection(),
		"insert into entries"
		"("
			"journal_id, "
			"comment, "
			"account_id, "
			"amount, "
			"is_reconciled"
		") "
		"values"
		"("
			":journal_id, "
			":comment, "
			":account_id, "
			":amount, "
			":is_reconciled"
		")"
	);
	process_saving_statement(inserter);
	return;
}

void
EntryImpl::do_ghostify()
{
	clear(m_data->journal_id);
	clear(m_data->account);
	clear(m_data->comment);
	clear(m_data->amount);
	clear(m_data->is_reconciled);
	return;
}

void
EntryImpl::do_remove()
{
	PhatbooksDatabaseConnection::BalanceCacheAttorney::mark_as_stale
	(	database_connection(),
		account().id()
	);
	std::string const statement_text =
		"delete from " + primary_table_name() + " where " +
		primary_key_name() + " = :p";
	SQLStatement statement(database_connection(), statement_text);
	statement.bind(":p", id());
	statement.step_final();
}

std::string
EntryImpl::primary_table_name()
{
	return "entries";
}

std::string
EntryImpl::exclusive_table_name()
{
	return primary_table_name();
}

std::string
EntryImpl::primary_key_name()
{
	return "entry_id";
}

void
EntryImpl::mimic(EntryImpl& rhs)
{
	load();
	EntryImpl temp(*this);
	temp.set_account(rhs.account());
	temp.set_comment(rhs.comment());
	temp.set_amount(rhs.amount());
	temp.set_whether_reconciled(rhs.is_reconciled());
	swap(temp);
	return;
}

}  // namespace phatbooks
<commit_msg>Closed a loophole whereby envelope balances were not being updated in BalanceCache, in some circumstances where they should be. Previously, when calling EntryImpl::do_save_existing(...), only the CURRENT Account of the EntryImpl was being marked as stale. In fact, the previous Account of the EntryImpl (i.e. the one residing in the database just prior to the EntryImpl being re-saved to the database) also needs to be marked as stale. I have now fixed this.<commit_after>
/** \file entry_impl.cpp
 *
 * \brief Source file pertaining to EntryImpl class.
 *
 * \author Matthew Harvey
 * \date 04 July 2012.
 *
 * Copyright (c) 2012, Matthew Harvey. All rights reserved.
 */

#include "entry_impl.hpp"
#include "account.hpp"
#include "b_string.hpp"
#include "commodity.hpp"
#include "phatbooks_database_connection.hpp"
#include "b_string.hpp"
#include <sqloxx/database_connection.hpp>
#include <sqloxx/general_typedefs.hpp>
#include <sqloxx/handle.hpp>
#include <sqloxx/sql_statement.hpp>
#include <boost/shared_ptr.hpp>
#include <jewel/debug_log.hpp>
#include <jewel/decimal.hpp>
#include <jewel/optional.hpp>
#include <string>

using sqloxx::SQLStatement;
using boost::shared_ptr;
using jewel::clear;
using jewel::Decimal;
using jewel::value;
using std::string;

#ifdef DEBUG
	#include <iomanip>
	#include <iostream>
#endif

namespace phatbooks
{

void EntryImpl::setup_tables(PhatbooksDatabaseConnection& dbc)
{
	dbc.execute_sql
	(	"create table entries"
		"("
			"entry_id integer primary key autoincrement, "
			"journal_id not null references journals, "
			"comment text, "
			"account_id not null references accounts, "
			"amount integer not null, "
			"is_reconciled not null references booleans"
		");"
	);
	dbc.execute_sql
	(	"create index entry_journal_index on entries(journal_id); "
	);
	return;
}

EntryImpl::EntryImpl
(	IdentityMap& p_identity_map
):
	PersistentObject(p_identity_map),
	m_data(new EntryData)
{
}

EntryImpl::EntryImpl
(	IdentityMap& p_identity_map,
	Id p_id
):
	PersistentObject(p_identity_map, p_id),
	m_data(new EntryData)
{
}

EntryImpl::~EntryImpl()
{
	/* If m_data is a smart pointer, this is not required.
	delete m_data;
	m_data = 0;
	*/
}

void
EntryImpl::set_journal_id(Id p_journal_id)
{
	load();
	m_data->journal_id = p_journal_id;
	return;
}

void
EntryImpl::set_account(Account const& p_account)
{
	load();
	m_data->account = p_account;
	return;
}

void
EntryImpl::set_comment(BString const& p_comment)
{
	load();
	m_data->comment = p_comment;
	return;
}

void
EntryImpl::set_amount(Decimal const& p_amount)
{
	load();
	m_data->amount = p_amount;
	return;
}

void
EntryImpl::set_whether_reconciled(bool p_is_reconciled)
{
	load();
	m_data->is_reconciled = p_is_reconciled;
	return;
}

Account
EntryImpl::account()
{
	load();
	return value(m_data->account);
}

BString
EntryImpl::comment()
{
	load();
	return value(m_data->comment);
}

jewel::Decimal
EntryImpl::amount()
{
	load();
	return value(m_data->amount);
}

bool
EntryImpl::is_reconciled()
{
	load();
	return value(m_data->is_reconciled);
}

void
EntryImpl::swap(EntryImpl& rhs)
{
	swap_base_internals(rhs);
	using std::swap;
	swap(m_data, rhs.m_data);
	return;
}

EntryImpl::EntryImpl(EntryImpl const& rhs):
	PersistentObject(rhs),
	m_data(new EntryData(*(rhs.m_data)))
{
}

void
EntryImpl::do_load()
{
	EntryImpl temp(*this);
	SQLStatement statement
	(	database_connection(),
		"select account_id, comment, amount, journal_id, is_reconciled "
		" from entries where "
		"entry_id = :p"
	);
	statement.bind(":p", id());
	statement.step();
	Account const acct
	(	database_connection(),
		statement.extract<Account::Id>(0)
	);
	Decimal const amt
	(	statement.extract<Decimal::int_type>(2),
		acct.commodity().precision()
	);

	temp.m_data->account = acct;
	temp.m_data->comment = std8_to_bstring(statement.extract<string>(1));
	temp.m_data->amount = amt;
	temp.m_data->journal_id = statement.extract<Id>(3);
	temp.m_data->is_reconciled =
		static_cast<bool>(statement.extract<int>(4));

	swap(temp);
	return;
}

void
EntryImpl::process_saving_statement(SQLStatement& statement)
{
	statement.bind(":journal_id", value(m_data->journal_id));
	statement.bind(":comment", bstring_to_std8(value(m_data->comment)));
	statement.bind(":account_id", value(m_data->account).id());
	statement.bind(":amount", m_data->amount->intval());
	statement.bind
	(	":is_reconciled",
		static_cast<int>(value(m_data->is_reconciled))
	);
	statement.step_final();
	return;
}

void
EntryImpl::do_save_existing()
{
	// We need to get the old Account so we can mark it as stale
	SQLStatement old_account_capturer
	(	database_connection(),
		"select account_id from entries where entry_id = :p"
	);
	old_account_capturer.bind(":p", id());
	old_account_capturer.step();
	PhatbooksDatabaseConnection::BalanceCacheAttorney::mark_as_stale
	(	database_connection(),
		old_account_capturer.extract<Account::Id>(0)
	);
	old_account_capturer.step_final();

	// And we also need to mark the new Account as stale
	PhatbooksDatabaseConnection::BalanceCacheAttorney::mark_as_stale
	(	database_connection(),
		account().id()
	);

	// And now we can update the Entry itself
	SQLStatement updater
	(	database_connection(),
		"update entries set "
		"journal_id = :journal_id, "
		"comment = :comment, "
		"account_id = :account_id, "
		"amount = :amount, "
		"is_reconciled = :is_reconciled "
		"where entry_id = :entry_id"
	);
	updater.bind(":entry_id", id());
	process_saving_statement(updater);
	return;
}

void
EntryImpl::do_save_new()
{
	PhatbooksDatabaseConnection::BalanceCacheAttorney::mark_as_stale
	(	database_connection(),
		account().id()
	);
	SQLStatement inserter
	(	database_connection(),
		"insert into entries"
		"("
			"journal_id, "
			"comment, "
			"account_id, "
			"amount, "
			"is_reconciled"
		") "
		"values"
		"("
			":journal_id, "
			":comment, "
			":account_id, "
			":amount, "
			":is_reconciled"
		")"
	);
	process_saving_statement(inserter);
	return;
}

void
EntryImpl::do_ghostify()
{
	clear(m_data->journal_id);
	clear(m_data->account);
	clear(m_data->comment);
	clear(m_data->amount);
	clear(m_data->is_reconciled);
	return;
}

void
EntryImpl::do_remove()
{
	PhatbooksDatabaseConnection::BalanceCacheAttorney::mark_as_stale
	(	database_connection(),
		account().id()
	);
	std::string const statement_text =
		"delete from " + primary_table_name() + " where " +
		primary_key_name() + " = :p";
	SQLStatement statement(database_connection(), statement_text);
	statement.bind(":p", id());
	statement.step_final();
}

std::string
EntryImpl::primary_table_name()
{
	return "entries";
}

std::string
EntryImpl::exclusive_table_name()
{
	return primary_table_name();
}

std::string
EntryImpl::primary_key_name()
{
	return "entry_id";
}

void
EntryImpl::mimic(EntryImpl& rhs)
{
	load();
	EntryImpl temp(*this);
	temp.set_account(rhs.account());
	temp.set_comment(rhs.comment());
	temp.set_amount(rhs.amount());
	temp.set_whether_reconciled(rhs.is_reconciled());
	swap(temp);
	return;
}

}  // namespace phatbooks
<|endoftext|>


<commit_before>#include "runner.h"

#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "e2e-examples/gcs/crc32c/crc32c.h"

using ::google::storage::v2::Object;
using ::google::storage::v2::ReadObjectRequest;
using ::google::storage::v2::ReadObjectResponse;
using ::google::storage::v2::StartResumableWriteRequest;
using ::google::storage::v2::StartResumableWriteResponse;
using ::google::storage::v2::WriteObjectRequest;
using ::google::storage::v2::WriteObjectResponse;

int32_t GetChannelId(void* stub_handle) {
  static std::unordered_map<void*, int32_t> handle_to_id_map;
  static absl::Mutex lock;

  absl::MutexLock l(&lock);
  auto i = handle_to_id_map.find(stub_handle);
  if (i != handle_to_id_map.end()) {
    return i->second;
  }

  auto new_id = int32_t(handle_to_id_map.size() + 1);
  handle_to_id_map[stub_handle] = new_id;
  return new_id;
}

std::string ToV2BucketName(absl::string_view bucket_name) {
  static const absl::string_view V2_BUCKET_NAME_PREFIX = "projects/_/buckets/";
  return absl::StrCat(V2_BUCKET_NAME_PREFIX, bucket_name);
}

void ApplyCallTimeout(grpc::ClientContext* context, absl::Duration timeout) {
  if (timeout != absl::InfiniteDuration()) {
    context->set_deadline(
        std::chrono::system_clock::now() +
        std::chrono::milliseconds(absl::ToInt64Milliseconds(timeout)));
  }
}

Runner::Runner(Runner::Parameter parameter,
               std::shared_ptr<RunnerWatcher> watcher)
    : parameter_(parameter), watcher_(watcher) {}

void Runner::Run() {
  switch (parameter_.operation_type) {
    case OperationType::Read:
      return_code_ = RunRead();
      break;
    case OperationType::Write:
      return_code_ = RunWrite();
      break;
    default:
      return_code_ = false;
      break;
  }
}

bool Runner::RunRead() {
  for (int run = 0; run < parameter_.runs; run++) {
    auto storage = parameter_.storage_stub_provider->GetStorageStub();

    std::string object;
    if (parameter_.object_stop > 0) {
      int offset = run + ((parameter_.id - 1) * parameter_.runs);
      int index =
          (offset % (parameter_.object_stop - parameter_.object_start)) +
          parameter_.object_start;
      char real_object[256];
      int cx = snprintf(real_object, sizeof(real_object),
                        parameter_.object_format.c_str(), index);
      if (cx < 0) {
        std::cerr << "snprintf(object, index) failed" << std::endl;
        return false;
      }
      object = real_object;
    } else {
      object = parameter_.object;
    }

    ReadObjectRequest request;
    request.set_bucket(ToV2BucketName(parameter_.bucket));
    request.set_object(object);
    if (parameter_.read_offset >= 0) {
      request.set_read_offset(parameter_.read_offset);
    }
    if (parameter_.read_limit >= 0) {
      request.set_read_limit(parameter_.read_limit);
    }

    absl::Time run_start = absl::Now();
    grpc::ClientContext context;
    ApplyCallTimeout(&context, parameter_.timeout);
    std::unique_ptr<grpc::ClientReader<ReadObjectResponse>> reader =
        storage.stub->ReadObject(&context, request);

    int64_t total_bytes = 0;
    std::vector<RunnerWatcher::Chunk> chunks;
    chunks.reserve(256);

    ReadObjectResponse response;
    while (reader->Read(&response)) {
      const auto& content = response.checksummed_data().content();
      int64_t content_size = content.size();

      if (parameter_.check_crc32c) {
        uint32_t content_crc = response.checksummed_data().crc32c();
        uint32_t calculated_crc =
            crc32c_value((const uint8_t*)content.c_str(), content_size);
        if (content_crc != calculated_crc) {
          std::cerr << "CRC32 is not identical. " << content_crc << " vs "
                    << calculated_crc << std::endl;
          break;
        }
      }

      RunnerWatcher::Chunk chunk = {absl::Now(), content_size};
      chunks.push_back(chunk);
      total_bytes += content_size;
    }

    auto status = reader->Finish();
    absl::Time run_end = absl::Now();

    if (!status.ok()) {
      std::cerr << "Download Failure!" << std::endl;
      std::cerr << "Peer: " << context.peer() << std::endl;
      std::cerr << "Status: " << std::endl;
      std::cerr << "- Code: " << status.error_code() << std::endl;
      std::cerr << "- Message: " << status.error_message() << std::endl;
      std::cerr << "- Details: " << status.error_details() << std::endl;
    }

    auto keep_going = parameter_.storage_stub_provider->ReportResult(
        storage.handle, status, context, run_end - run_start, total_bytes);

    watcher_->NotifyCompleted(
        OperationType::Read, parameter_.id, GetChannelId(storage.handle),
        context.peer(), parameter_.bucket, object, status, total_bytes,
        run_start, run_end - run_start, std::move(chunks));

    /*
    bool used_directpath = context.peer().rfind("ipv6:[2001:") == 0;
    if (used_directpath ^ absl::GetFlag(FLAGS_directpath)) {
      std::cerr << "DirectPath flag is " << absl::GetFlag(FLAGS_directpath)
           << ", but using directpath is " << used_directpath << std::endl;
      std::cerr << "Peer was " << context.peer() << endl;
      return;
    }
    */

    if (keep_going == false) {
      return false;
    }
  }

  return true;
}

static std::vector<char> GetRandomData(size_t size) {
  std::vector<char> content(size);
  int* const s = reinterpret_cast<int*>(&(*content.begin()));
  int* const e = reinterpret_cast<int*>(&(*content.rbegin()));
  for (int* c = s; c < e; c += 1) {
    *c = rand();
  }
  return content;
}

bool Runner::RunWrite() {
  const int64_t max_chunk_size = 2097152;
  const std::vector<char> content = GetRandomData(max_chunk_size);

  for (int run = 0; run < parameter_.runs; run++) {
    auto storage = parameter_.storage_stub_provider->GetStorageStub();

    std::string object;
    if (parameter_.object_stop > 0) {
      std::cerr << "write doesn't support object_stop" << std::endl;
      return false;
    } else {
      char real_object[256];
      int cx = snprintf(real_object, sizeof(real_object), "%s_%d_%d",
                        parameter_.object.c_str(), parameter_.id, run);
      if (cx < 0) {
        std::cerr << "snprintf(object, index) failed" << std::endl;
        return false;
      }
      object = real_object;
    }

    absl::Time run_start = absl::Now();
    uint32_t object_crc32c = 0;

    std::string upload_id;
    if (parameter_.resumable_write) {
      grpc::ClientContext context;
      ApplyCallTimeout(&context, parameter_.timeout);
      StartResumableWriteRequest start_request;
      auto resource =
          start_request.mutable_write_object_spec()->mutable_resource();
      resource->set_bucket(ToV2BucketName(parameter_.bucket));
      resource->set_name(object);
      StartResumableWriteResponse start_response;
      auto status = storage.stub->StartResumableWrite(&context, start_request,
                                                      &start_response);
      if (!status.ok()) {
        std::cerr << "StartResumableWrite failed code=" << status.error_code()
                  << std::endl;
        return false;
      }
      upload_id = start_response.upload_id();
    }

    grpc::ClientContext context;
    ApplyCallTimeout(&context, parameter_.timeout);
    WriteObjectResponse reply;
    std::unique_ptr<grpc::ClientWriter<WriteObjectRequest>> writer(
        storage.stub->WriteObject(&context, &reply));

    int64_t total_bytes = 0;
    std::vector<RunnerWatcher::Chunk> chunks;
    chunks.reserve(256);

    for (int64_t o = 0; o < parameter_.write_size; o += max_chunk_size) {
      bool first_request = o == 0;
      bool last_request = (o + max_chunk_size) >= parameter_.write_size;
      int64_t chunk_size = std::min(max_chunk_size, parameter_.write_size - o);

      WriteObjectRequest request;
      if (first_request) {
        if (parameter_.resumable_write) {
          request.set_upload_id(upload_id);
        } else {
          auto resource =
              request.mutable_write_object_spec()->mutable_resource();
          resource->set_bucket(ToV2BucketName(parameter_.bucket));
          resource->set_name(object);
        }
      }

      request.mutable_checksummed_data()->set_content(&content[0], chunk_size);
      if (parameter_.check_crc32c) {
        uint32_t crc32c = crc32c_value((const uint8_t*)&content[0], chunk_size);
        request.mutable_checksummed_data()->set_crc32c(crc32c);

        object_crc32c = crc32c_extend(object_crc32c,
                                      (const uint8_t*)&content[0], chunk_size);
      }

      request.set_write_offset(o);
      if (last_request) {
        request.set_finish_write(true);
        if (parameter_.check_crc32c) {
          request.mutable_object_checksums()->set_crc32c(object_crc32c);
        }
      }

      if (!writer->Write(request)) break;

      RunnerWatcher::Chunk chunk = {absl::Now(), chunk_size};
      chunks.push_back(chunk);
      total_bytes += chunk_size;
    }
    writer->WritesDone();

    auto status = writer->Finish();
    absl::Time run_end = absl::Now();

    if (!status.ok()) {
      std::cerr << "Upload Failure!" << std::endl;
      std::cerr << "Peer: " << context.peer() << std::endl;
      std::cerr << "Status: " << std::endl;
      std::cerr << "- Code: " << status.error_code() << std::endl;
      std::cerr << "- Message: " << status.error_message() << std::endl;
      std::cerr << "- Details: " << status.error_details() << std::endl;
    }

    auto keep_going = parameter_.storage_stub_provider->ReportResult(
        storage.handle, status, context, run_end - run_start, total_bytes);

    watcher_->NotifyCompleted(
        OperationType::Write, parameter_.id, GetChannelId(storage.handle),
        context.peer(), parameter_.bucket, object, status, total_bytes,
        run_start, run_end - run_start, std::move(chunks));

    if (keep_going == false) {
      return false;
    }
  }

  return true;
}
<commit_msg>More info to error message<commit_after>#include "runner.h"

#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "e2e-examples/gcs/crc32c/crc32c.h"

using ::google::storage::v2::Object;
using ::google::storage::v2::ReadObjectRequest;
using ::google::storage::v2::ReadObjectResponse;
using ::google::storage::v2::StartResumableWriteRequest;
using ::google::storage::v2::StartResumableWriteResponse;
using ::google::storage::v2::WriteObjectRequest;
using ::google::storage::v2::WriteObjectResponse;

int32_t GetChannelId(void* stub_handle) {
  static std::unordered_map<void*, int32_t> handle_to_id_map;
  static absl::Mutex lock;

  absl::MutexLock l(&lock);
  auto i = handle_to_id_map.find(stub_handle);
  if (i != handle_to_id_map.end()) {
    return i->second;
  }

  auto new_id = int32_t(handle_to_id_map.size() + 1);
  handle_to_id_map[stub_handle] = new_id;
  return new_id;
}

std::string ToV2BucketName(absl::string_view bucket_name) {
  static const absl::string_view V2_BUCKET_NAME_PREFIX = "projects/_/buckets/";
  return absl::StrCat(V2_BUCKET_NAME_PREFIX, bucket_name);
}

void ApplyCallTimeout(grpc::ClientContext* context, absl::Duration timeout) {
  if (timeout != absl::InfiniteDuration()) {
    context->set_deadline(
        std::chrono::system_clock::now() +
        std::chrono::milliseconds(absl::ToInt64Milliseconds(timeout)));
  }
}

Runner::Runner(Runner::Parameter parameter,
               std::shared_ptr<RunnerWatcher> watcher)
    : parameter_(parameter), watcher_(watcher) {}

void Runner::Run() {
  switch (parameter_.operation_type) {
    case OperationType::Read:
      return_code_ = RunRead();
      break;
    case OperationType::Write:
      return_code_ = RunWrite();
      break;
    default:
      return_code_ = false;
      break;
  }
}

bool Runner::RunRead() {
  for (int run = 0; run < parameter_.runs; run++) {
    auto storage = parameter_.storage_stub_provider->GetStorageStub();

    std::string object;
    if (parameter_.object_stop > 0) {
      int offset = run + ((parameter_.id - 1) * parameter_.runs);
      int index =
          (offset % (parameter_.object_stop - parameter_.object_start)) +
          parameter_.object_start;
      char real_object[256];
      int cx = snprintf(real_object, sizeof(real_object),
                        parameter_.object_format.c_str(), index);
      if (cx < 0) {
        std::cerr << "snprintf(object, index) failed" << std::endl;
        return false;
      }
      object = real_object;
    } else {
      object = parameter_.object;
    }

    ReadObjectRequest request;
    request.set_bucket(ToV2BucketName(parameter_.bucket));
    request.set_object(object);
    if (parameter_.read_offset >= 0) {
      request.set_read_offset(parameter_.read_offset);
    }
    if (parameter_.read_limit >= 0) {
      request.set_read_limit(parameter_.read_limit);
    }

    absl::Time run_start = absl::Now();
    grpc::ClientContext context;
    ApplyCallTimeout(&context, parameter_.timeout);
    std::unique_ptr<grpc::ClientReader<ReadObjectResponse>> reader =
        storage.stub->ReadObject(&context, request);

    int64_t total_bytes = 0;
    std::vector<RunnerWatcher::Chunk> chunks;
    chunks.reserve(256);

    ReadObjectResponse response;
    while (reader->Read(&response)) {
      const auto& content = response.checksummed_data().content();
      int64_t content_size = content.size();

      if (parameter_.check_crc32c) {
        uint32_t content_crc = response.checksummed_data().crc32c();
        uint32_t calculated_crc =
            crc32c_value((const uint8_t*)content.c_str(), content_size);
        if (content_crc != calculated_crc) {
          std::cerr << "CRC32 is not identical. " << content_crc << " vs "
                    << calculated_crc << std::endl;
          break;
        }
      }

      RunnerWatcher::Chunk chunk = {absl::Now(), content_size};
      chunks.push_back(chunk);
      total_bytes += content_size;
    }

    auto status = reader->Finish();
    absl::Time run_end = absl::Now();

    if (!status.ok()) {
      std::cerr << "Download Failure!" << std::endl;
      std::cerr << "Peer:   " << context.peer() << std::endl;
      std::cerr << "Start:  " << run_start << std::endl;
      std::cerr << "End:    " << run_end << std::endl;
      std::cerr << "Elased: " << (run_end - run_start) << std::endl;
      std::cerr << "Bucket: " << parameter_.bucket.c_str() << std::endl;
      std::cerr << "Object: " << object.c_str() << std::endl;
      std::cerr << "Bytes:  " << total_bytes << std::endl;
      std::cerr << "Status: " << std::endl;
      std::cerr << "- Code:    " << status.error_code() << std::endl;
      std::cerr << "- Message: " << status.error_message() << std::endl;
      std::cerr << "- Details: " << status.error_details() << std::endl;
    }

    auto keep_going = parameter_.storage_stub_provider->ReportResult(
        storage.handle, status, context, run_end - run_start, total_bytes);

    watcher_->NotifyCompleted(
        OperationType::Read, parameter_.id, GetChannelId(storage.handle),
        context.peer(), parameter_.bucket, object, status, total_bytes,
        run_start, run_end - run_start, std::move(chunks));

    /*
    bool used_directpath = context.peer().rfind("ipv6:[2001:") == 0;
    if (used_directpath ^ absl::GetFlag(FLAGS_directpath)) {
      std::cerr << "DirectPath flag is " << absl::GetFlag(FLAGS_directpath)
           << ", but using directpath is " << used_directpath << std::endl;
      std::cerr << "Peer was " << context.peer() << endl;
      return;
    }
    */

    if (keep_going == false) {
      return false;
    }
  }

  return true;
}

static std::vector<char> GetRandomData(size_t size) {
  std::vector<char> content(size);
  int* const s = reinterpret_cast<int*>(&(*content.begin()));
  int* const e = reinterpret_cast<int*>(&(*content.rbegin()));
  for (int* c = s; c < e; c += 1) {
    *c = rand();
  }
  return content;
}

bool Runner::RunWrite() {
  const int64_t max_chunk_size = 2097152;
  const std::vector<char> content = GetRandomData(max_chunk_size);

  for (int run = 0; run < parameter_.runs; run++) {
    auto storage = parameter_.storage_stub_provider->GetStorageStub();

    std::string object;
    if (parameter_.object_stop > 0) {
      std::cerr << "write doesn't support object_stop" << std::endl;
      return false;
    } else {
      char real_object[256];
      int cx = snprintf(real_object, sizeof(real_object), "%s_%d_%d",
                        parameter_.object.c_str(), parameter_.id, run);
      if (cx < 0) {
        std::cerr << "snprintf(object, index) failed" << std::endl;
        return false;
      }
      object = real_object;
    }

    absl::Time run_start = absl::Now();
    uint32_t object_crc32c = 0;

    std::string upload_id;
    if (parameter_.resumable_write) {
      grpc::ClientContext context;
      ApplyCallTimeout(&context, parameter_.timeout);
      StartResumableWriteRequest start_request;
      auto resource =
          start_request.mutable_write_object_spec()->mutable_resource();
      resource->set_bucket(ToV2BucketName(parameter_.bucket));
      resource->set_name(object);
      StartResumableWriteResponse start_response;
      auto status = storage.stub->StartResumableWrite(&context, start_request,
                                                      &start_response);
      if (!status.ok()) {
        std::cerr << "StartResumableWrite failed code=" << status.error_code()
                  << std::endl;
        return false;
      }
      upload_id = start_response.upload_id();
    }

    grpc::ClientContext context;
    ApplyCallTimeout(&context, parameter_.timeout);
    WriteObjectResponse reply;
    std::unique_ptr<grpc::ClientWriter<WriteObjectRequest>> writer(
        storage.stub->WriteObject(&context, &reply));

    int64_t total_bytes = 0;
    std::vector<RunnerWatcher::Chunk> chunks;
    chunks.reserve(256);

    for (int64_t o = 0; o < parameter_.write_size; o += max_chunk_size) {
      bool first_request = o == 0;
      bool last_request = (o + max_chunk_size) >= parameter_.write_size;
      int64_t chunk_size = std::min(max_chunk_size, parameter_.write_size - o);

      WriteObjectRequest request;
      if (first_request) {
        if (parameter_.resumable_write) {
          request.set_upload_id(upload_id);
        } else {
          auto resource =
              request.mutable_write_object_spec()->mutable_resource();
          resource->set_bucket(ToV2BucketName(parameter_.bucket));
          resource->set_name(object);
        }
      }

      request.mutable_checksummed_data()->set_content(&content[0], chunk_size);
      if (parameter_.check_crc32c) {
        uint32_t crc32c = crc32c_value((const uint8_t*)&content[0], chunk_size);
        request.mutable_checksummed_data()->set_crc32c(crc32c);

        object_crc32c = crc32c_extend(object_crc32c,
                                      (const uint8_t*)&content[0], chunk_size);
      }

      request.set_write_offset(o);
      if (last_request) {
        request.set_finish_write(true);
        if (parameter_.check_crc32c) {
          request.mutable_object_checksums()->set_crc32c(object_crc32c);
        }
      }

      if (!writer->Write(request)) break;

      RunnerWatcher::Chunk chunk = {absl::Now(), chunk_size};
      chunks.push_back(chunk);
      total_bytes += chunk_size;
    }
    writer->WritesDone();

    auto status = writer->Finish();
    absl::Time run_end = absl::Now();

    if (!status.ok()) {
      std::cerr << "Upload Failure!" << std::endl;
      std::cerr << "Peer:   " << context.peer() << std::endl;
      std::cerr << "Start:  " << run_start << std::endl;
      std::cerr << "End:    " << run_end << std::endl;
      std::cerr << "Elased: " << (run_end - run_start) << std::endl;
      std::cerr << "Bucket: " << parameter_.bucket.c_str() << std::endl;
      std::cerr << "Object: " << object.c_str() << std::endl;
      std::cerr << "Bytes:  " << total_bytes << std::endl;
      std::cerr << "Status: " << std::endl;
      std::cerr << "- Code:    " << status.error_code() << std::endl;
      std::cerr << "- Message: " << status.error_message() << std::endl;
      std::cerr << "- Details: " << status.error_details() << std::endl;
    }

    auto keep_going = parameter_.storage_stub_provider->ReportResult(
        storage.handle, status, context, run_end - run_start, total_bytes);

    watcher_->NotifyCompleted(
        OperationType::Write, parameter_.id, GetChannelId(storage.handle),
        context.peer(), parameter_.bucket, object, status, total_bytes,
        run_start, run_end - run_start, std::move(chunks));

    if (keep_going == false) {
      return false;
    }
  }

  return true;
}
<|endoftext|>


<commit_before>#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;

int main()
{

}
<commit_msg>HDU4812<commit_after>#pragma comment(linker,"/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int MAXN=1E5+5;
const int MAXM=2E5+5;
#define P 1000003
struct node{
    int nxt,v;
}Edge[MAXM];
int head[MAXN],cnt_e;
int inv[P],val[MAXN],siz[MAXN],mx_rt,rt,dis[MAXN],stk[MAXN],top,id[MAXN],mp[P];
bool vis[MAXN];
int L,R;
inline void add(int u,int v)
{
    Edge[++cnt_e].v=v;
    Edge[cnt_e].nxt=head[u];
    head[u]=cnt_e;
}
void init()
{
    inv[1]=1;
    for(int i=2;i<P;i++)
    {
        int a=P/i,b=P%i;
        inv[i]=(1ll*(-a)*inv[b]%P+P)%P;
    }
}
int k;
void get_root(int x,int fa,int sz)
{
    int mx=1;siz[x]=1;
    for(int i=head[x];i;i=Edge[i].nxt)
    {
        int v=Edge[i].v;
        if(vis[v]||v==fa) continue;
        get_root(v,x,sz);
        siz[x]+=siz[v];
        mx=max(mx,siz[v]);
    }
    mx=max(mx,sz-siz[x]);
    if(mx<mx_rt) mx_rt=mx,rt=x;
}
void dfs(int x,int fa)
{
    stk[++top]=dis[x];id[top]=x;
    for(int i=head[x];i;i=Edge[i].nxt)
    {
        int v=Edge[i].v;
        if(vis[v]||v==fa) continue;
        dis[v]=(1ll*dis[x]*val[v])%P;
        dfs(v,x);
    }
}
void query(int val,int _id)
{
    int tmp=(1ll*k*inv[val])%P;
    if(!mp[tmp]) return;
    int __id=mp[tmp];
    if(_id>__id) swap(_id,__id);
    if(_id<L||(_id==L&&__id<R)) L=_id,R=__id;
}
void solve(int x)
{
    vis[x]=1;mp[val[x]]=x;
    for(int i=head[x];i;i=Edge[i].nxt)
    {
        int v=Edge[i].v;
        if(vis[v]) continue;
        dis[v]=val[v]%P;top=0;
        dfs(v,0);
        for(int j=1;j<=top;j++)  query(stk[j],id[j]);
        dis[v]=(1ll*val[v]*val[x])%P;top=0;
        dfs(v,0);
        for(int j=1;j<=top;j++) if(!mp[stk[j]]||mp[stk[j]]>id[j]) mp[stk[j]]=id[j];
    }
    mp[val[x]]=0;
    for(int i=head[x];i;i=Edge[i].nxt)
    {
        int v=Edge[i].v;
        if(vis[v]) continue;
        dis[v]=(1ll*val[v]*val[x])%P;top=0;
        dfs(v,0);
        for(int j=1;j<=top;j++) mp[stk[j]]=0;
    }
    for(int i=head[x];i;i=Edge[i].nxt)
    {
        int v=Edge[i].v;
        if(vis[v]) continue;
        mx_rt=MAXN+10;
        get_root(v,0,siz[v]);
        solve(rt);
    }
}
int n,u,v;
int main()
{
    init();
    while(~scanf("%d%d",&n,&k))
    {
        memset(head,0,sizeof head);
        memset(vis,0,sizeof vis);
        cnt_e=0;
        for(int i=1;i<=n;i++) scanf("%d",&val[i]);
        for(int i=1;i<n;i++) scanf("%d%d",&u,&v),add(u,v),add(v,u);
        mx_rt=MAXN+10;
        get_root(1,0,n);
        L=R=P;
        solve(rt);
        if(L!=P) printf("%d %d\n",L,R);
        else puts("No solution");
    }
}
<|endoftext|>


<commit_before>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include "packet.h"

#define USAGE "Usage:\r\nc \r\n[tux machine number] \r\n[probability of packet corruption in int form] \r\n[probability of packet loss in int form] \r\n[probability of packet delay] \r\n[length of delay in ms] \r\n"
#define PORT 10038
#define PAKSIZE 512
#define ACK 0
#define NAK 1
#define BUFSIZE 505
#define FILENAME "Testfile"
#define TIMEOUT 15 //in ms
#define WIN_SIZE 16

using namespace std;

bool isvpack(unsigned char * p);
bool init(int argc, char** argv);
bool loadFile();
bool getFile();
bool sendFile();
bool isAck();
void handleAck();
void handleNak(int& x);
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb);
Packet createPacket(int index);
void loadWindow();
bool sendPacket();
bool getGet();

struct sockaddr_in a;
struct sockaddr_in ca;
socklen_t calen;
int rlen;
int s;
bool ack;
string fstr;
char * file;
int probCorrupt;
int probLoss;
int probDelay;
int delayT;
Packet p;
Packet window[16];
int length;
bool dropPck;
bool delayPck;
int toms;
unsigned char b[BUFSIZE];
int base;

int main(int argc, char** argv) {

  if(!init(argc, argv)) return -1;

  if(sendFile()) cout << "GET Testfile complete." << endl;

  return 0;
}

bool init(int argc, char** argv){

  if(argc != 6) {
    cout << USAGE << endl;
    return false;
  }

  char * probCorruptStr = argv[2];
  probCorrupt = boost::lexical_cast<int>(probCorruptStr);
  char * probLossStr = argv[3];
  probLoss = boost::lexical_cast<int>(probLossStr);
  char * probDelayStr = argv[4];
  probDelay = boost::lexical_cast<int>(probDelayStr);
  char* delayTStr = argv[5];
  delayT = boost::lexical_cast<int>(delayTStr);

  struct timeval timeout;
  timeout.tv_usec = TIMEOUT * 1000;
  toms = TIMEOUT;

  /* Create our socket. */
  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    cout << "Socket creation failed. (socket s)" << endl;
    return 0;
  }

  setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));

  /*
   * Bind our socket to an IP (whatever the computer decides)
   * and a specified port.
   *
   */

  if (!loadFile()) {
    cout << "Loading file failed. (filename FILENAME)" << endl;
    return false;
  }

  memset((char *)&a, 0, sizeof(a));
  a.sin_family = AF_INET;
  a.sin_addr.s_addr = htonl(INADDR_ANY);
  a.sin_port = htons(PORT);

  if (bind(s, (struct sockaddr *)&a, sizeof(a)) < 0) {
    cout << "Socket binding failed. (socket s, address a)" << endl;
    return 0;
  }

  fstr = string(file);
  cout << "File: " << endl << fstr << endl;

  base = 0;
  dropPck = false;
  calen = sizeof(ca);

  getGet();

  return true;
}

bool getGet(){
	unsigned char packet[PAKSIZE + 1];
	rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);
	return (rlen > 0) ? true : false;
}

bool isvpack(unsigned char * p) {
  cout << endl << "=== IS VALID PACKET TESTING" << endl;

  char * sns = new char[2];
  memcpy(sns, &p[0], 1);
  sns[1] = '\0';

  char * css = new char[7];
  memcpy(css, &p[1], 6);
  css[6] = '\0';

  char * db = new char[121 + 1];
  memcpy(db, &p[2], 121);
  db[121] = '\0';

  cout << "Seq. num: " << sns << endl;
  cout << "Checksum: " << css << endl;
  cout << "Message: " << db << endl;

  int sn = boost::lexical_cast<int>(sns);
  int cs = boost::lexical_cast<int>(css);

  Packet pk (0, db);
  pk.setSequenceNum(sn);

  // change to validate based on checksum and sequence number

  if(sn == 0) return false; //doesn't matter, only for the old version (netwark)
  if(cs != pk.generateCheckSum()) return false;
  return true;
}

bool getFile(){

  /* Loop forever, waiting for messages from a client. */
  cout << "Waiting on port " << PORT << "..." << endl;

  ofstream file("Dumpfile");

  for (;;) {
    unsigned char packet[PAKSIZE + 1];
    unsigned char dataPull[PAKSIZE - 7 + 1];
    rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);

    for(int x = 0; x < PAKSIZE - 7; x++) {
      dataPull[x] = packet[x + 7];
    }
    dataPull[PAKSIZE - 7] = '\0';
    packet[PAKSIZE] = '\0';
    if (rlen > 0) {
      char * css = new char[6];
      memcpy(css, &packet[1], 5);
      css[5] = '\0';
      cout << endl << endl << "=== RECEIPT" << endl;
      cout << "Seq. num: " << packet[0] << endl;
      cout << "Checksum: " << css << endl;
      cout << "Received message: " << dataPull << endl;
      cout << "Sent response: ";
      if(isvpack(packet)) {
        ack = ACK;
        //seqNum = (seqNum) ? false : true;
        file << dataPull;
      } else {
        ack = NAK;
      }
      cout << ((ack == ACK) ? "ACK" : "NAK") << endl;
      Packet p (false, reinterpret_cast<const char *>(dataPull));
      p.setCheckSum(boost::lexical_cast<int>(css));
      p.setAckNack(ack);

      if(sendto(s, p.str(), PAKSIZE, 0, (struct sockaddr *)&ca, calen) < 0) {
        cout << "Acknowledgement failed. (socket s, acknowledgement message ack, client address ca, client address length calen)" << endl;
        return 0;
      }
      delete css;
    }
  }
  file.close();
  return true;
}

bool loadFile() {

  ifstream is (FILENAME, ifstream::binary);

  if(is) {
    is.seekg(0, is.end);
    length = is.tellg();
    is.seekg(0, is.beg);

    file = new char[length];

    cout << "Reading " << length << " characters..." << endl;
    is.read(file, length);

    if(!is) { cout << "File reading failed. (filename " << FILENAME << "). Only " << is.gcount() << " could be read."; return false; }
    is.close();
  }
  return true;
}

void loadWindow(){
	for(int i = base; i < base + WIN_SIZE; i++) {
		window[i-base] = createPacket(i);
		if(strlen(window[i-base].getDataBuffer()) < BUFSIZE && window[i-base].chksm()) {
			cout << "In loadWindow's secret base, index is: " << i-base << endl;
			for(++i; i < base + WIN_SIZE; i++){
				window[i-base].loadDataBuffer("\0");
			}

		}
		/*cout << "window[i-base] seq. num: " << window[i-base].getSequenceNum() << endl;*/
	}

		/*cout << "packet " << base + 1 << ": " << window[1].str() << endl;
		cout << "packet " << base + 2 << ": " << window[2].str() << endl;*/
}

bool sendFile() {
	/*Currently causes the program to only send the first 16 packets of file out
		requires additional code later to sendFile again with updated window*/
	fd_set stReadFDS;

	struct timeval stTimeOut;

	FD_ZERO(&stReadFDS);
	stTimeOut.tv_sec = 0;
	stTimeOut.tv_usec = 1000 * TIMEOUT;
	FD_SET(s, &stReadFDS);

	base = 0;
	int desc_ready;
	int finale = -1;
	int max_sd;
	bool hasRead = false;
	while(base * BUFSIZE < length) {
		loadWindow();

		if(p.str()[0] == '\0') finale = p.getSequenceNum();
		for(int x = 0; x < WIN_SIZE; x++) {
			p = window[x];
			if(!sendPacket()) continue;
		}
		while(finale < 15) {
			cout << endl << "beginning of loop " << x << endl;
			FD_ZERO(&stReadFDS);
			stTimeOut.tv_sec = 0;
			stTimeOut.tv_usec = 1000 * TIMEOUT;
			FD_SET(s, &stReadFDS);

			max_sd = s;
			cout << endl << "before select" << endl;
			int t = select(max_sd + 1, &stReadFDS, NULL, NULL, &stTimeOut);
			cout << "after select" << endl;
			if (t == -1){
				perror("select()");
			}
			if (t == 0) {
				cout << "=== ACK TIMEOUT (select)" << endl;

			}
			desc_ready = t;
			for(int u = 0; u <= max_sd  &&  desc_ready > 0; u++){
				if(recvfrom(s, b, BUFSIZE + 7, 0, (struct sockaddr *)&ca, &calen) < 0) {
					cout << "=== ACK TIMEOUT (recvfrom)" << endl;
				} else hasRead = true;
				if(!hasRead) continue;
				if(isAck()) {
					cout << "if isAck()" << endl;
					handleAck();
					finale++;
				} else {
					cout << "Not an ACK!" << endl;
				}
			}
			cout << "end of loop " << x << endl;
			/*if(finale > 0 && base == finale) {cout << "Finale: " << finale << endl; break;}
			memset(b, 0, BUFSIZE);
			}*/

		}

	if(sendto(s, "\0", BUFSIZE, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Final package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
	}
	return true;
}

Packet createPacket(int index){
    string mstr = fstr.substr(index * BUFSIZE, BUFSIZE);

	if(mstr.length() < BUFSIZE) {
		cout << "Null terminated mstr." << endl;
		mstr[length - (index * BUFSIZE)] = '\0';
    }

	cout << "index: " << index << endl;
    return Packet (index, mstr.c_str());
}

bool sendPacket(){
	cout << endl;
    cout << "=== TRANSMISSION START" << endl;
	cout << "Sequence number before gremlin function: " << p.getSequenceNum() << endl;
    int pc = probCorrupt; int pl = probLoss; int pd = probDelay;
	bool* pckStatus = gremlin(&p, pc, pl, pd);

	dropPck = pckStatus[0];
	delayPck = pckStatus[1];

	if (dropPck == true) return false;
	if (delayPck == true) p.setAckNack(1);

    if(sendto(s, p.str(), BUFSIZE + 8, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
    }
    return true;
}
bool isAck() {
    cout << endl << "=== SERVER RESPONSE TEST" << endl;
    cout << "Data: " << b << endl;
    if(b[6] == '\0') return true;
    else return false;
}
void handleAck() {
	int ack = boost::lexical_cast<int>(b);
	if(base < ack) base = ack;
	cout << "Window base: " << base << endl;
}
void handleNak(int& x) {

      char * sns = new char[2];
      memcpy(sns, &b[0], 1);
      sns[1] = '\0';

      char * css = new char[5];
      memcpy(css, &b[1], 5);

      char * db = new char[BUFSIZE + 1];
      memcpy(db, &b[2], BUFSIZE);
      db[BUFSIZE] = '\0';

      cout << "Sequence number: " << sns << endl;
      cout << "Checksum: " << css << endl;

      Packet pk (0, db);
      pk.setSequenceNum(boost::lexical_cast<int>(sns));
      pk.setCheckSum(boost::lexical_cast<int>(css));

      if(!pk.chksm()) x--;
      else x = (x - 2 > 0) ? x - 2 : 0;
}
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb){

  bool* packStatus = new bool[2];
  int r = rand() % 100;

  cout << "Corruption probability: " << corruptProb << endl;
  cout << "Random number: " << r << endl;

  packStatus[0] = false;
  packStatus[1] = false;

  if(r <= (lossProb)){
	packStatus[0] = true;
    cout << "Dropped!" << endl;
  }
  else if(r <= (delayProb)){
	  packStatus[1] = true;
	  cout << "Delayed!" << endl;
  }
  else if(r <= (corruptProb)){
    cout << "Corrupted!" << endl;
	cout << "Seq. num (pre-gremlin): " << pack->getSequenceNum() << endl;
    pack->loadDataBuffer((char*)"GREMLIN LOL");
  }
  cout << "Seq. num: " << pack->getSequenceNum() << endl;
  cout << "Checksum: " << pack->getCheckSum() << endl;
  //cout << "Message: "  << pack->getDataBuffer() << endl;

  return packStatus;
}<commit_msg>dumb mistake fix<commit_after>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include "packet.h"

#define USAGE "Usage:\r\nc \r\n[tux machine number] \r\n[probability of packet corruption in int form] \r\n[probability of packet loss in int form] \r\n[probability of packet delay] \r\n[length of delay in ms] \r\n"
#define PORT 10038
#define PAKSIZE 512
#define ACK 0
#define NAK 1
#define BUFSIZE 505
#define FILENAME "Testfile"
#define TIMEOUT 15 //in ms
#define WIN_SIZE 16

using namespace std;

bool isvpack(unsigned char * p);
bool init(int argc, char** argv);
bool loadFile();
bool getFile();
bool sendFile();
bool isAck();
void handleAck();
void handleNak(int& x);
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb);
Packet createPacket(int index);
void loadWindow();
bool sendPacket();
bool getGet();

struct sockaddr_in a;
struct sockaddr_in ca;
socklen_t calen;
int rlen;
int s;
bool ack;
string fstr;
char * file;
int probCorrupt;
int probLoss;
int probDelay;
int delayT;
Packet p;
Packet window[16];
int length;
bool dropPck;
bool delayPck;
int toms;
unsigned char b[BUFSIZE];
int base;

int main(int argc, char** argv) {

  if(!init(argc, argv)) return -1;

  if(sendFile()) cout << "GET Testfile complete." << endl;

  return 0;
}

bool init(int argc, char** argv){

  if(argc != 6) {
    cout << USAGE << endl;
    return false;
  }

  char * probCorruptStr = argv[2];
  probCorrupt = boost::lexical_cast<int>(probCorruptStr);
  char * probLossStr = argv[3];
  probLoss = boost::lexical_cast<int>(probLossStr);
  char * probDelayStr = argv[4];
  probDelay = boost::lexical_cast<int>(probDelayStr);
  char* delayTStr = argv[5];
  delayT = boost::lexical_cast<int>(delayTStr);

  struct timeval timeout;
  timeout.tv_usec = TIMEOUT * 1000;
  toms = TIMEOUT;

  /* Create our socket. */
  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    cout << "Socket creation failed. (socket s)" << endl;
    return 0;
  }

  setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));

  /*
   * Bind our socket to an IP (whatever the computer decides)
   * and a specified port.
   *
   */

  if (!loadFile()) {
    cout << "Loading file failed. (filename FILENAME)" << endl;
    return false;
  }

  memset((char *)&a, 0, sizeof(a));
  a.sin_family = AF_INET;
  a.sin_addr.s_addr = htonl(INADDR_ANY);
  a.sin_port = htons(PORT);

  if (bind(s, (struct sockaddr *)&a, sizeof(a)) < 0) {
    cout << "Socket binding failed. (socket s, address a)" << endl;
    return 0;
  }

  fstr = string(file);
  cout << "File: " << endl << fstr << endl;

  base = 0;
  dropPck = false;
  calen = sizeof(ca);

  getGet();

  return true;
}

bool getGet(){
	unsigned char packet[PAKSIZE + 1];
	rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);
	return (rlen > 0) ? true : false;
}

bool isvpack(unsigned char * p) {
  cout << endl << "=== IS VALID PACKET TESTING" << endl;

  char * sns = new char[2];
  memcpy(sns, &p[0], 1);
  sns[1] = '\0';

  char * css = new char[7];
  memcpy(css, &p[1], 6);
  css[6] = '\0';

  char * db = new char[121 + 1];
  memcpy(db, &p[2], 121);
  db[121] = '\0';

  cout << "Seq. num: " << sns << endl;
  cout << "Checksum: " << css << endl;
  cout << "Message: " << db << endl;

  int sn = boost::lexical_cast<int>(sns);
  int cs = boost::lexical_cast<int>(css);

  Packet pk (0, db);
  pk.setSequenceNum(sn);

  // change to validate based on checksum and sequence number

  if(sn == 0) return false; //doesn't matter, only for the old version (netwark)
  if(cs != pk.generateCheckSum()) return false;
  return true;
}

bool getFile(){

  /* Loop forever, waiting for messages from a client. */
  cout << "Waiting on port " << PORT << "..." << endl;

  ofstream file("Dumpfile");

  for (;;) {
    unsigned char packet[PAKSIZE + 1];
    unsigned char dataPull[PAKSIZE - 7 + 1];
    rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);

    for(int x = 0; x < PAKSIZE - 7; x++) {
      dataPull[x] = packet[x + 7];
    }
    dataPull[PAKSIZE - 7] = '\0';
    packet[PAKSIZE] = '\0';
    if (rlen > 0) {
      char * css = new char[6];
      memcpy(css, &packet[1], 5);
      css[5] = '\0';
      cout << endl << endl << "=== RECEIPT" << endl;
      cout << "Seq. num: " << packet[0] << endl;
      cout << "Checksum: " << css << endl;
      cout << "Received message: " << dataPull << endl;
      cout << "Sent response: ";
      if(isvpack(packet)) {
        ack = ACK;
        //seqNum = (seqNum) ? false : true;
        file << dataPull;
      } else {
        ack = NAK;
      }
      cout << ((ack == ACK) ? "ACK" : "NAK") << endl;
      Packet p (false, reinterpret_cast<const char *>(dataPull));
      p.setCheckSum(boost::lexical_cast<int>(css));
      p.setAckNack(ack);

      if(sendto(s, p.str(), PAKSIZE, 0, (struct sockaddr *)&ca, calen) < 0) {
        cout << "Acknowledgement failed. (socket s, acknowledgement message ack, client address ca, client address length calen)" << endl;
        return 0;
      }
      delete css;
    }
  }
  file.close();
  return true;
}

bool loadFile() {

  ifstream is (FILENAME, ifstream::binary);

  if(is) {
    is.seekg(0, is.end);
    length = is.tellg();
    is.seekg(0, is.beg);

    file = new char[length];

    cout << "Reading " << length << " characters..." << endl;
    is.read(file, length);

    if(!is) { cout << "File reading failed. (filename " << FILENAME << "). Only " << is.gcount() << " could be read."; return false; }
    is.close();
  }
  return true;
}

void loadWindow(){
	for(int i = base; i < base + WIN_SIZE; i++) {
		window[i-base] = createPacket(i);
		if(strlen(window[i-base].getDataBuffer()) < BUFSIZE && window[i-base].chksm()) {
			cout << "In loadWindow's secret base, index is: " << i-base << endl;
			for(++i; i < base + WIN_SIZE; i++){
				window[i-base].loadDataBuffer("\0");
			}

		}
		/*cout << "window[i-base] seq. num: " << window[i-base].getSequenceNum() << endl;*/
	}

		/*cout << "packet " << base + 1 << ": " << window[1].str() << endl;
		cout << "packet " << base + 2 << ": " << window[2].str() << endl;*/
}

bool sendFile() {
	/*Currently causes the program to only send the first 16 packets of file out
		requires additional code later to sendFile again with updated window*/
	fd_set stReadFDS;

	struct timeval stTimeOut;

	FD_ZERO(&stReadFDS);
	stTimeOut.tv_sec = 0;
	stTimeOut.tv_usec = 1000 * TIMEOUT;
	FD_SET(s, &stReadFDS);

	base = 0;
	int desc_ready;
	int finale = -1;
	int max_sd;
	bool hasRead = false;
	while(base * BUFSIZE < length) {
		loadWindow();

		if(p.str()[0] == '\0') finale = p.getSequenceNum();
		for(int x = 0; x < WIN_SIZE; x++) {
			p = window[x];
			if(!sendPacket()) continue;
		}
		while(finale < 15) {
			cout << endl << "beginning of loop " << finale << endl;
			FD_ZERO(&stReadFDS);
			stTimeOut.tv_sec = 0;
			stTimeOut.tv_usec = 1000 * TIMEOUT;
			FD_SET(s, &stReadFDS);

			max_sd = s;
			cout << endl << "before select" << endl;
			int t = select(max_sd + 1, &stReadFDS, NULL, NULL, &stTimeOut);
			cout << "after select" << endl;
			if (t == -1){
				perror("select()");
			}
			if (t == 0) {
				cout << "=== ACK TIMEOUT (select)" << endl;

			}
			desc_ready = t;
			for(int u = 0; u <= max_sd  &&  desc_ready > 0; u++){
				if(recvfrom(s, b, BUFSIZE + 7, 0, (struct sockaddr *)&ca, &calen) < 0) {
					cout << "=== ACK TIMEOUT (recvfrom)" << endl;
				} else hasRead = true;
				if(!hasRead) continue;
				if(isAck()) {
					cout << "if isAck()" << endl;
					handleAck();
					finale++;
				} else {
					cout << "Not an ACK!" << endl;
				}
			}
			cout << "end of loop " << x << endl;
			/*if(finale > 0 && base == finale) {cout << "Finale: " << finale << endl; break;}
			memset(b, 0, BUFSIZE);
			}*/

		}

	if(sendto(s, "\0", BUFSIZE, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Final package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
	}
	return true;
}

Packet createPacket(int index){
    string mstr = fstr.substr(index * BUFSIZE, BUFSIZE);

	if(mstr.length() < BUFSIZE) {
		cout << "Null terminated mstr." << endl;
		mstr[length - (index * BUFSIZE)] = '\0';
    }

	cout << "index: " << index << endl;
    return Packet (index, mstr.c_str());
}

bool sendPacket(){
	cout << endl;
    cout << "=== TRANSMISSION START" << endl;
	cout << "Sequence number before gremlin function: " << p.getSequenceNum() << endl;
    int pc = probCorrupt; int pl = probLoss; int pd = probDelay;
	bool* pckStatus = gremlin(&p, pc, pl, pd);

	dropPck = pckStatus[0];
	delayPck = pckStatus[1];

	if (dropPck == true) return false;
	if (delayPck == true) p.setAckNack(1);

    if(sendto(s, p.str(), BUFSIZE + 8, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
    }
    return true;
}
bool isAck() {
    cout << endl << "=== SERVER RESPONSE TEST" << endl;
    cout << "Data: " << b << endl;
    if(b[6] == '\0') return true;
    else return false;
}
void handleAck() {
	int ack = boost::lexical_cast<int>(b);
	if(base < ack) base = ack;
	cout << "Window base: " << base << endl;
}
void handleNak(int& x) {

      char * sns = new char[2];
      memcpy(sns, &b[0], 1);
      sns[1] = '\0';

      char * css = new char[5];
      memcpy(css, &b[1], 5);

      char * db = new char[BUFSIZE + 1];
      memcpy(db, &b[2], BUFSIZE);
      db[BUFSIZE] = '\0';

      cout << "Sequence number: " << sns << endl;
      cout << "Checksum: " << css << endl;

      Packet pk (0, db);
      pk.setSequenceNum(boost::lexical_cast<int>(sns));
      pk.setCheckSum(boost::lexical_cast<int>(css));

      if(!pk.chksm()) x--;
      else x = (x - 2 > 0) ? x - 2 : 0;
}
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb){

  bool* packStatus = new bool[2];
  int r = rand() % 100;

  cout << "Corruption probability: " << corruptProb << endl;
  cout << "Random number: " << r << endl;

  packStatus[0] = false;
  packStatus[1] = false;

  if(r <= (lossProb)){
	packStatus[0] = true;
    cout << "Dropped!" << endl;
  }
  else if(r <= (delayProb)){
	  packStatus[1] = true;
	  cout << "Delayed!" << endl;
  }
  else if(r <= (corruptProb)){
    cout << "Corrupted!" << endl;
	cout << "Seq. num (pre-gremlin): " << pack->getSequenceNum() << endl;
    pack->loadDataBuffer((char*)"GREMLIN LOL");
  }
  cout << "Seq. num: " << pack->getSequenceNum() << endl;
  cout << "Checksum: " << pack->getCheckSum() << endl;
  //cout << "Message: "  << pack->getDataBuffer() << endl;

  return packStatus;
}<|endoftext|>