<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

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

#include <stdio.h>
#include <string.h>
#include "tensorflow/lite/experimental/micro/debug_log.h"

// These are set by openmv py_tf.c code to redirect printing to an error message
// buffer...

static char *py_tf_putchar_buffer = NULL;
static size_t py_tf_putchar_buffer_len = 0;

extern "C" void DebugLog(const char* s) {
  for (size_t i = 0, j = strlen(s); i < j; i++) {
    if (py_tf_putchar_buffer_len) {
      *py_tf_putchar_buffer++ = s[i];
      py_tf_putchar_buffer_len--;
    } else {
      putchar(s[i]);
    }
  }
}
<commit_msg>Change printf to puts<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

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

#include <stdio.h>
#include <string.h>
#include "tensorflow/lite/experimental/micro/debug_log.h"

// These are set by openmv py_tf.c code to redirect printing to an error message
// buffer...

static char *py_tf_putchar_buffer = NULL;
static size_t py_tf_putchar_buffer_len = 0;

extern "C" void DebugLog(const char* s) {
<<<<<<< HEAD
  for (size_t i = 0, j = strlen(s); i < j; i++) {
    if (py_tf_putchar_buffer_len) {
      *py_tf_putchar_buffer++ = s[i];
      py_tf_putchar_buffer_len--;
    } else {
      putchar(s[i]);
    }
  }
=======
  puts(s);
>>>>>>> Change printf to puts
}
<|endoftext|>


<commit_before>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <memory>
#include <sstream>
#include <string>

#include "absl/strings/str_join.h"
#include "tensorflow/lite/core/api/error_reporter.h"
#include "tensorflow/lite/model_builder.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "tensorflow/lite/schema/schema_utils.h"
#include "tensorflow/lite/tools/versioning/gpu_compatibility.h"
#include "tensorflow/lite/version.h"

namespace tflite {

namespace {

// Dump details of the given tensor.
void dump_tensor_detail(std::stringstream& out_stream,
                        const tflite::Tensor* tensor, const int tensor_idx) {
  out_stream << "T#" << tensor_idx;
  out_stream << "(" << tensor->name()->str() << ") ";
  // Prints `shape_signature` instead of `shape` if it's available since it
  // supports dynamic shapes.
  if (tensor->shape_signature()) {
    out_stream << "shape_signature:[";
    for (int i = 0; i < tensor->shape_signature()->Length(); ++i) {
      const int j = tensor->shape_signature()->Get(i);
      out_stream << j;
      if (i != tensor->shape_signature()->Length() - 1) {
        out_stream << ", ";
      }
    }
    out_stream << "]";
  } else {
    out_stream << "shape:[";
    for (int i = 0; i < tensor->shape()->Length(); ++i) {
      const int j = tensor->shape()->Get(i);
      out_stream << j;
      if (i != tensor->shape()->Length() - 1) {
        out_stream << ", ";
      }
    }
    out_stream << "]";
  }
  out_stream << ", type:" << EnumNameTensorType(tensor->type());
  out_stream << "\n";
}

// Dump list of input or output tensors.
void dump_tensor_list(std::stringstream& out_stream,
                      const flatbuffers::Vector<int32_t>* tensors,
                      bool verbose = false) {
  for (int i = 0; i < tensors->Length(); ++i) {
    const int tensor_idx = tensors->Get(i);
    if (verbose) {
      out_stream << "tensor #" << tensor_idx;
    } else {
      out_stream << "T#" << tensor_idx;
    }
    if (i != tensors->Length() - 1) {
      if (verbose) {
        out_stream << " and ";
      } else {
        out_stream << ", ";
      }
    }
  }
}

// Returns the string representation of the given OperatorCode.
const std::string get_op_name(const OperatorCode* op_code) {
  auto builtin_code = GetBuiltinCode(op_code);
  if (builtin_code != BuiltinOperator_CUSTOM) {
    return EnumNameBuiltinOperator(builtin_code);
  } else {
    return op_code->custom_code()->str();
  }
}

// Dump the given Operator node.
void dump_node(std::stringstream& out_stream, const int node_no,
               const OperatorCode* op_code, const Operator* op,
               const SubGraph* subgraph) {
  out_stream << "Op#" << node_no << " " << get_op_name(op_code);
  out_stream << "(";
  dump_tensor_list(out_stream, op->inputs());
  out_stream << ") -> [";
  dump_tensor_list(out_stream, op->outputs());
  out_stream << "]\n";
}

// Dump the summary of the given TFLite flatbuffer model. It's printed at the
// beginning of the analyzer output.
void dump_model_summary(std::stringstream& out_stream,
                        const ::tflite::Model* model) {
  auto* subgraphs = model->subgraphs();
  out_stream
      << "Your TFLite model has ‘" << subgraphs->Length()
      << "’ subgraph(s). In the subgraph description below,\nT# represents the "
         "Tensor numbers. ";
  if (subgraphs->Length() > 0 && subgraphs->Get(0)->operators()->Length() > 0) {
    const Operator* first_op = subgraphs->Get(0)->operators()->Get(0);
    const OperatorCode* first_op_code =
        model->operator_codes()->Get(first_op->opcode_index());
    out_stream << "For example, in Subgraph#0, the "
               << get_op_name(first_op_code) << " op takes\n";
    dump_tensor_list(out_stream, first_op->inputs(), /*verbose=*/true);
    out_stream << " as input and produces ";
    dump_tensor_list(out_stream, first_op->outputs(), /*verbose=*/true);
    out_stream << " as output.\n\n";
  }
}

}  // namespace

class StreamErrorReporter : public ErrorReporter {
 public:
  explicit StreamErrorReporter(std::stringstream* out_stream)
      : out_stream_(out_stream) {}
  int Report(const char* format, va_list args) override {
    char buffer[1024];
    int size = vsnprintf(buffer, sizeof(buffer), format, args);
    *out_stream_ << buffer;
    return size;
  }

 private:
  std::stringstream* out_stream_;
};

std::string model_analyzer(const std::string& model_file_or_buffer,
                           bool input_is_filepath,
                           bool check_gpu_compatibility) {
  std::stringstream out_stream;
  StreamErrorReporter error_reporter(&out_stream);
  std::unique_ptr<FlatBufferModel> fb_model;
  if (input_is_filepath) {
    fb_model = FlatBufferModel::BuildFromFile(model_file_or_buffer.c_str(),
                                              &error_reporter);
    if (!fb_model) {
      out_stream << "Failed to mmap model " << model_file_or_buffer;
      return out_stream.str();
    }
  } else {
    fb_model = FlatBufferModel::BuildFromBuffer(model_file_or_buffer.c_str(),
                                                model_file_or_buffer.size(),
                                                &error_reporter);
    if (!fb_model) {
      out_stream << "Failed to mmap the given model buffer.";
      return out_stream.str();
    }
  }
  const ::tflite::Model* model = fb_model->GetModel();
  auto* subgraphs = model->subgraphs();

  dump_model_summary(out_stream, model);

  bool model_is_gpu_compatibile = true;
  for (int i = 0; i < subgraphs->Length(); ++i) {
    std::vector<int> gpu_incompatibile_nodes;
    const SubGraph* subgraph = subgraphs->Get(i);
    out_stream << "Subgraph#" << i;
    if (subgraph->name()) {
      out_stream << " " << subgraph->name()->str();
    }
    out_stream << "(";
    dump_tensor_list(out_stream, subgraph->inputs());
    out_stream << ") -> [";
    dump_tensor_list(out_stream, subgraph->outputs());
    out_stream << "]\n";
    for (int j = 0; j < subgraph->operators()->Length(); ++j) {
      const Operator* op = subgraph->operators()->Get(j);
      const OperatorCode* op_code =
          model->operator_codes()->Get(op->opcode_index());
      out_stream << "  ";  // indents for operators
      dump_node(out_stream, /*node_no=*/j, op_code, op, subgraph);
      if (check_gpu_compatibility) {
        auto status =
            CheckGpuDelegateCompatibility(op_code, op, subgraph, model);
        if (!status.ok()) {
          gpu_incompatibile_nodes.push_back(j);
          out_stream << "GPU COMPATIBILITY WARNING: " << status.message()
                     << "\n";
        }
      }
    }
    if (!gpu_incompatibile_nodes.empty()) {
      model_is_gpu_compatibile = false;
      out_stream << "\nGPU COMPATIBILITY WARNING: Subgraph#" << i
                 << " has GPU delegate compatibility issues at nodes "
                 << absl::StrJoin(gpu_incompatibile_nodes, ", ")
                 << " with TFLite runtime version " << TF_VERSION_STRING
                 << "\n";
    }

    // Dump Subgraph Tensors.
    out_stream << "\nTensors of Subgraph#" << i << "\n";
    auto tensors = subgraph->tensors();
    for (int j = 0; j < tensors->Length(); ++j) {
      auto tensor = tensors->Get(j);
      out_stream << "  ";  // indents for tensors
      dump_tensor_detail(out_stream, tensor, j);
    }
    out_stream << "\n";
  }
  if (check_gpu_compatibility && model_is_gpu_compatibile) {
    out_stream
        << "\nYour model looks compatibile with GPU delegate"
        << " with TFLite runtime version " << TF_VERSION_STRING
        << ".\nBut it doesn't guarantee that your model works well with GPU "
           "delegate.\nThere could be some runtime incompatibililty happen.\n";
  }
  return out_stream.str();
}

}  // namespace tflite
<commit_msg>Update model_analyzer to some stats<commit_after>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <memory>
#include <sstream>
#include <string>

#include "absl/strings/str_join.h"
#include "tensorflow/lite/core/api/error_reporter.h"
#include "tensorflow/lite/model_builder.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "tensorflow/lite/schema/schema_utils.h"
#include "tensorflow/lite/tools/versioning/gpu_compatibility.h"
#include "tensorflow/lite/version.h"

namespace tflite {

namespace {

const float kThreshold_zero_buffer_ratio = 10.0f;

// Dump details of the given tensor.
void dump_tensor_detail(std::stringstream& out_stream,
                        const tflite::Tensor* tensor, const int tensor_idx) {
  out_stream << "T#" << tensor_idx;
  out_stream << "(" << tensor->name()->str() << ") ";
  // Prints `shape_signature` instead of `shape` if it's available since it
  // supports dynamic shapes.
  if (tensor->shape_signature()) {
    out_stream << "shape_signature:[";
    for (int i = 0; i < tensor->shape_signature()->Length(); ++i) {
      const int j = tensor->shape_signature()->Get(i);
      out_stream << j;
      if (i != tensor->shape_signature()->Length() - 1) {
        out_stream << ", ";
      }
    }
    out_stream << "]";
  } else {
    out_stream << "shape:[";
    for (int i = 0; i < tensor->shape()->Length(); ++i) {
      const int j = tensor->shape()->Get(i);
      out_stream << j;
      if (i != tensor->shape()->Length() - 1) {
        out_stream << ", ";
      }
    }
    out_stream << "]";
  }
  out_stream << ", type:" << EnumNameTensorType(tensor->type());
  out_stream << "\n";
}

// Dump list of input or output tensors.
void dump_tensor_list(std::stringstream& out_stream,
                      const flatbuffers::Vector<int32_t>* tensors,
                      bool verbose = false) {
  for (int i = 0; i < tensors->Length(); ++i) {
    const int tensor_idx = tensors->Get(i);
    if (verbose) {
      out_stream << "tensor #" << tensor_idx;
    } else {
      out_stream << "T#" << tensor_idx;
    }
    if (i != tensors->Length() - 1) {
      if (verbose) {
        out_stream << " and ";
      } else {
        out_stream << ", ";
      }
    }
  }
}

// Returns the string representation of the given OperatorCode.
const std::string get_op_name(const OperatorCode* op_code) {
  auto builtin_code = GetBuiltinCode(op_code);
  if (builtin_code != BuiltinOperator_CUSTOM) {
    return EnumNameBuiltinOperator(builtin_code);
  } else {
    return op_code->custom_code()->str();
  }
}

// Dump the given Operator node.
void dump_node(std::stringstream& out_stream, const int node_no,
               const OperatorCode* op_code, const Operator* op,
               const SubGraph* subgraph) {
  out_stream << "Op#" << node_no << " " << get_op_name(op_code);
  out_stream << "(";
  dump_tensor_list(out_stream, op->inputs());
  out_stream << ") -> [";
  dump_tensor_list(out_stream, op->outputs());
  out_stream << "]\n";
}

// Dump the summary of the given TFLite flatbuffer model. It's printed at the
// beginning of the analyzer output.
void dump_model_summary(std::stringstream& out_stream,
                        const ::tflite::Model* model) {
  auto* subgraphs = model->subgraphs();
  out_stream
      << "Your TFLite model has ‘" << subgraphs->Length()
      << "’ subgraph(s). In the subgraph description below,\nT# represents the "
         "Tensor numbers. ";
  if (subgraphs->Length() > 0 && subgraphs->Get(0)->operators()->Length() > 0) {
    const Operator* first_op = subgraphs->Get(0)->operators()->Get(0);
    const OperatorCode* first_op_code =
        model->operator_codes()->Get(first_op->opcode_index());
    out_stream << "For example, in Subgraph#0, the "
               << get_op_name(first_op_code) << " op takes\n";
    dump_tensor_list(out_stream, first_op->inputs(), /*verbose=*/true);
    out_stream << " as input and produces ";
    dump_tensor_list(out_stream, first_op->outputs(), /*verbose=*/true);
    out_stream << " as output.\n\n";
  }
}

// Dump the statistics of the given TFLite flatbuffer model. It's printed at the
// end of the analyzer output.
void dump_model_stats(std::stringstream& out_stream,
                      const ::tflite::Model* model, size_t model_size) {
  size_t total_buffer_size = 0;
  size_t total_zero_buffer_size = 0;
  auto* buffers = model->buffers();
  for (int i = 0; i < buffers->size(); ++i) {
    const tflite::Buffer* buffer = buffers->Get(i);
    if (buffer->data() == nullptr) {
      continue;
    }
    bool is_all_zeros = true;
    const unsigned char* data = buffer->data()->data();
    for (int j = 0; j < buffer->data()->size(); ++j) {
      if (data[j] != 0) {
        is_all_zeros = false;
        break;
      }
    }
    if (is_all_zeros) {
      total_zero_buffer_size += buffer->data()->size();
    }
    total_buffer_size += buffer->data()->size();
  }

  out_stream << "\n";
  char temp[2048];
  snprintf(temp, sizeof(temp), "%24s: %10zu bytes\n", "Model size", model_size);
  out_stream << temp;
  snprintf(
      temp, sizeof(temp), "%24s: %10zu bytes (%05.2f %%)\n",
      "Non-data buffer size", model_size - total_buffer_size,
      (static_cast<float>(model_size - total_buffer_size) / model_size * 100));
  out_stream << temp;
  snprintf(temp, sizeof(temp), "%24s: %10zu bytes (%05.2f %%)\n",
           "Total data buffer size", total_buffer_size,
           (static_cast<float>(total_buffer_size) / model_size * 100));
  out_stream << temp;
  float zero_buffer_ratio =
      static_cast<float>(total_zero_buffer_size) / model_size * 100;
  snprintf(temp, sizeof(temp), "%24s: %10zu bytes (%05.2f %%)\n",
           "(Zero value buffers)", total_zero_buffer_size, zero_buffer_ratio);
  out_stream << temp;
  out_stream
      << "\n"
      << "* Buffers of TFLite model are mostly used for constant tensors.\n";
  out_stream << "  And zero value buffers are buffers filled with zeros.\n";
  if (zero_buffer_ratio > kThreshold_zero_buffer_ratio) {
    out_stream << "  (Consider use "
                  "`converter._experimental_unfold_large_splat_constant` "
                  "to save the model size.)\n";
  }
  out_stream << "  Non-data buffers area are used to store operators, "
                "subgraphs and etc.\n";
  out_stream << "  You can find more details from "
                "https://github.com/tensorflow/tensorflow/blob/master/"
                "tensorflow/lite/schema/schema.fbs\n";
}

}  // namespace

class StreamErrorReporter : public ErrorReporter {
 public:
  explicit StreamErrorReporter(std::stringstream* out_stream)
      : out_stream_(out_stream) {}
  int Report(const char* format, va_list args) override {
    char buffer[1024];
    int size = vsnprintf(buffer, sizeof(buffer), format, args);
    *out_stream_ << buffer;
    return size;
  }

 private:
  std::stringstream* out_stream_;
};

std::string model_analyzer(const std::string& model_file_or_buffer,
                           bool input_is_filepath,
                           bool check_gpu_compatibility) {
  std::stringstream out_stream;
  StreamErrorReporter error_reporter(&out_stream);
  std::unique_ptr<FlatBufferModel> fb_model;
  if (input_is_filepath) {
    fb_model = FlatBufferModel::BuildFromFile(model_file_or_buffer.c_str(),
                                              &error_reporter);
    if (!fb_model) {
      out_stream << "Failed to mmap model " << model_file_or_buffer;
      return out_stream.str();
    }
  } else {
    fb_model = FlatBufferModel::BuildFromBuffer(model_file_or_buffer.c_str(),
                                                model_file_or_buffer.size(),
                                                &error_reporter);
    if (!fb_model) {
      out_stream << "Failed to mmap the given model buffer.";
      return out_stream.str();
    }
  }
  const ::tflite::Model* model = fb_model->GetModel();
  auto* subgraphs = model->subgraphs();

  dump_model_summary(out_stream, model);

  bool model_is_gpu_compatibile = true;
  for (int i = 0; i < subgraphs->Length(); ++i) {
    std::vector<int> gpu_incompatibile_nodes;
    const SubGraph* subgraph = subgraphs->Get(i);
    out_stream << "Subgraph#" << i;
    if (subgraph->name()) {
      out_stream << " " << subgraph->name()->str();
    }
    out_stream << "(";
    dump_tensor_list(out_stream, subgraph->inputs());
    out_stream << ") -> [";
    dump_tensor_list(out_stream, subgraph->outputs());
    out_stream << "]\n";
    for (int j = 0; j < subgraph->operators()->Length(); ++j) {
      const Operator* op = subgraph->operators()->Get(j);
      const OperatorCode* op_code =
          model->operator_codes()->Get(op->opcode_index());
      out_stream << "  ";  // indents for operators
      dump_node(out_stream, /*node_no=*/j, op_code, op, subgraph);
      if (check_gpu_compatibility) {
        auto status =
            CheckGpuDelegateCompatibility(op_code, op, subgraph, model);
        if (!status.ok()) {
          gpu_incompatibile_nodes.push_back(j);
          out_stream << "GPU COMPATIBILITY WARNING: " << status.message()
                     << "\n";
        }
      }
    }
    if (!gpu_incompatibile_nodes.empty()) {
      model_is_gpu_compatibile = false;
      out_stream << "\nGPU COMPATIBILITY WARNING: Subgraph#" << i
                 << " has GPU delegate compatibility issues at nodes "
                 << absl::StrJoin(gpu_incompatibile_nodes, ", ")
                 << " with TFLite runtime version " << TF_VERSION_STRING
                 << "\n";
    }

    // Dump Subgraph Tensors.
    out_stream << "\nTensors of Subgraph#" << i << "\n";
    auto tensors = subgraph->tensors();
    for (int j = 0; j < tensors->Length(); ++j) {
      auto tensor = tensors->Get(j);
      out_stream << "  ";  // indents for tensors
      dump_tensor_detail(out_stream, tensor, j);
    }
    out_stream << "\n";
  }
  if (check_gpu_compatibility && model_is_gpu_compatibile) {
    out_stream
        << "\nYour model looks compatibile with GPU delegate"
        << " with TFLite runtime version " << TF_VERSION_STRING
        << ".\nBut it doesn't guarantee that your model works well with GPU "
           "delegate.\nThere could be some runtime incompatibililty happen.\n";
  }

  dump_model_stats(out_stream, model, fb_model->allocation()->bytes());

  return out_stream.str();
}

}  // namespace tflite
<|endoftext|>


<commit_before>#include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp>
#include <vigra/impex.hxx>

#include <util/Logger.h>

#include "ImageStackDirectoryWriter.h"

logger::LogChannel imagestackdirectorywriterlog("imagestackdirectorywriterlog", "[ImageStackDirectoryWriter] ");

ImageStackDirectoryWriter::ImageStackDirectoryWriter(std::string directory, std::string basename) :
	_directory(directory),
	_basename(basename),
	_dirty(false) {

	registerInput(_stack, "image stack");

	_stack.registerCallback(&ImageStackDirectoryWriter::onModified, this);
}

void
ImageStackDirectoryWriter::onModified(const pipeline::Modified&) {

	boost::mutex::scoped_lock lock(_dirtyMutex);

	LOG_DEBUG(imagestackdirectorywriterlog) << "stack changed" << std::endl;

	_dirty = true;
}

bool
ImageStackDirectoryWriter::write(std::string basename) {

	{
		boost::mutex::scoped_lock lock(_dirtyMutex);

		if (!_dirty)
			return false;

		_dirty = false;
	}

	LOG_DEBUG(imagestackdirectorywriterlog) << "attempting to write stack" << std::endl;

	if (!_stack.isSet()) {

		LOG_ERROR(imagestackdirectorywriterlog) << "no input image stack set" << std::endl;
		return false;
	}

	LOG_DEBUG(imagestackdirectorywriterlog) << "requesting image update" << std::endl;

	updateInputs();

	boost::unique_lock<boost::shared_mutex> lock(_stack->getMutex());

	boost::filesystem::path directory(_directory);

	if (!boost::filesystem::exists(directory))
		boost::filesystem::create_directory(directory);

	// save to file

	unsigned int i = 0;

	foreach (boost::shared_ptr<Image> image, *_stack) {

		std::stringstream number;
		number << std::setw(8) << std::setfill('0');
		number << i;

		// at least on Ubuntu 13.04, this maintains the exact values and does
		// not rescale
		std::string filename = _directory + "/" + _basename + basename + number.str() + ".tif";
		vigra::exportImage(vigra::srcImageRange(*image), vigra::ImageExportInfo(filename.c_str()).setPixelType("FLOAT"));

		i++;
	}

	LOG_DEBUG(imagestackdirectorywriterlog) << "images written" << std::endl;

	return true;
}
<commit_msg>removed lock from ImageStackDirectoryWriter<commit_after>#include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp>
#include <vigra/impex.hxx>

#include <util/Logger.h>

#include "ImageStackDirectoryWriter.h"

logger::LogChannel imagestackdirectorywriterlog("imagestackdirectorywriterlog", "[ImageStackDirectoryWriter] ");

ImageStackDirectoryWriter::ImageStackDirectoryWriter(std::string directory, std::string basename) :
	_directory(directory),
	_basename(basename),
	_dirty(false) {

	registerInput(_stack, "image stack");

	_stack.registerCallback(&ImageStackDirectoryWriter::onModified, this);
}

void
ImageStackDirectoryWriter::onModified(const pipeline::Modified&) {

	boost::mutex::scoped_lock lock(_dirtyMutex);

	LOG_DEBUG(imagestackdirectorywriterlog) << "stack changed" << std::endl;

	_dirty = true;
}

bool
ImageStackDirectoryWriter::write(std::string basename) {

	{
		boost::mutex::scoped_lock lock(_dirtyMutex);

		if (!_dirty)
			return false;

		_dirty = false;
	}

	LOG_DEBUG(imagestackdirectorywriterlog) << "attempting to write stack" << std::endl;

	if (!_stack.isSet()) {

		LOG_ERROR(imagestackdirectorywriterlog) << "no input image stack set" << std::endl;
		return false;
	}

	LOG_DEBUG(imagestackdirectorywriterlog) << "requesting image update" << std::endl;

	updateInputs();

	boost::filesystem::path directory(_directory);

	if (!boost::filesystem::exists(directory))
		boost::filesystem::create_directory(directory);

	// save to file

	unsigned int i = 0;

	foreach (boost::shared_ptr<Image> image, *_stack) {

		std::stringstream number;
		number << std::setw(8) << std::setfill('0');
		number << i;

		// at least on Ubuntu 13.04, this maintains the exact values and does
		// not rescale
		std::string filename = _directory + "/" + _basename + basename + number.str() + ".tif";
		vigra::exportImage(vigra::srcImageRange(*image), vigra::ImageExportInfo(filename.c_str()).setPixelType("FLOAT"));

		i++;
	}

	LOG_DEBUG(imagestackdirectorywriterlog) << "images written" << std::endl;

	return true;
}
<|endoftext|>


<commit_before>/**
 * @file device_properties.hxx
 * @author Cameron Shinn (ctshinn@ucdavis.edu)
 * @brief
 * @version 0.1
 * @date 2020-11-09
 *
 * @copyright Copyright (c) 2020
 *
 */
#pragma once

#include <gunrock/error.hxx>

#include <type_traits>

#ifndef SM_TARGET
  #define SM_TARGET 0
#endif

namespace gunrock {
namespace cuda {

/**
 * @brief CUDA dim3 template representation, since dim3 cannot be used as a
 * template argument
 * @tparam x_ Dimension in the X direction
 * @tparam y_ Dimension in the Y direction
 * @tparam z_ Dimension in the Z direction
 */
template<unsigned int x_, unsigned int y_ = 1, unsigned int z_ = 1>
struct dim3_t {
  enum : unsigned int { x = x_, y = y_, z = z_, size = x_ * y_ * z_ };
  static dim3 get_dim3() { return dim3(x, y, z); }
};

/**
 * @brief Struct holding kernel parameters will be passed in upon launch
 * @tparam block_dimensions_ Block dimensions to launch with
 * @tparam grid_dimensions_ Grid dimensions to launch with
 * @tparam shared_memory_bytes_ Amount of shared memory to allocate
 *
 * @todo dimensions should be dim3 instead of unsigned int
 */
template<
  typename block_dimensions_,
  typename grid_dimensions_,
  unsigned int shared_memory_bytes_ = 0
>
struct launch_params_t {
  typedef block_dimensions_ block_dimensions;
  typedef grid_dimensions_ grid_dimensions;
  enum : unsigned int { shared_memory_bytes = shared_memory_bytes_ };
};

/**
 * @brief Struct holding kernel parameters for a specific SM version
 * @tparam combined_ver_ Combined major and minor compute capability version
 * @tparam block_dimensions_ Block dimensions to launch with
 * @tparam grid_dimensions_ Grid dimensions to launch with
 * @tparam shared_memory_bytes_ Amount of shared memory to allocate
 */
template<
  unsigned int combined_ver_,
  typename block_dimensions_,
  typename grid_dimensions_,
  unsigned int shared_memory_bytes_ = 0
>
struct sm_launch_params_t : launch_params_t<
                              block_dimensions_,
                              grid_dimensions_,
                              shared_memory_bytes_
                            > {
  enum : unsigned int {combined_ver = combined_ver_};
};

template<
  typename block_dimensions_,
  typename grid_dimensions_,
  unsigned int shared_memory_bytes_ = 0
>
struct fallback_launch_params_t : sm_launch_params_t<
                                    0,
                                    block_dimensions_,
                                    grid_dimensions_,
                                    shared_memory_bytes_
                                  > {};

// Easier declaration inside launch box template
template<
  typename block_dimensions_,
  typename grid_dimensions_,
  unsigned int shared_memory_bytes_ = 0
>
using fallback_t = fallback_launch_params_t<
                     block_dimensions_,
                     grid_dimensions_,
                     shared_memory_bytes_
                   >;

// Easier declaration inside launch box template
template<
  unsigned int combined_ver_,
  typename block_dimensions_,
  typename grid_dimensions_,
  unsigned int shared_memory_bytes_ = 0
>
using sm_t = sm_launch_params_t<
               combined_ver_,
               block_dimensions_,
               grid_dimensions_,
               shared_memory_bytes_
             >;

// Define named sm_launch_params_t structs for each SM version
#define SM_LAUNCH_PARAMS(combined) \
template<                                        \
  typename block_dimensions_,                    \
  typename grid_dimensions_,                     \
  unsigned int shared_memory_bytes_ = 0          \
>                                                \
using sm_##combined##_t = sm_launch_params_t<    \
                            combined,            \
                            block_dimensions_,   \
                            grid_dimensions_,    \
                            shared_memory_bytes_ \
                          >;

// Add Hopper when the SM version number becomes known (presumably 90)
SM_LAUNCH_PARAMS(86)
SM_LAUNCH_PARAMS(80)
SM_LAUNCH_PARAMS(75)
SM_LAUNCH_PARAMS(72)
SM_LAUNCH_PARAMS(70)
SM_LAUNCH_PARAMS(62)
SM_LAUNCH_PARAMS(61)
SM_LAUNCH_PARAMS(60)
SM_LAUNCH_PARAMS(53)
SM_LAUNCH_PARAMS(52)
SM_LAUNCH_PARAMS(50)
SM_LAUNCH_PARAMS(37)
SM_LAUNCH_PARAMS(35)
SM_LAUNCH_PARAMS(30)

#undef SM_LAUNCH_PARAMS

template<typename... sm_lp_v>
struct device_launch_params_t;

// 1st to (N-1)th sm_launch_param_t template parameters
template<typename sm_lp_t, typename... sm_lp_v>
struct device_launch_params_t<sm_lp_t, sm_lp_v...> :
std::conditional_t<
  sm_lp_t::combined_ver == 0,
  device_launch_params_t<sm_lp_v..., sm_lp_t>,  // If found, move fallback_launch_params_t to end of template parameter pack
  std::conditional_t<                           // Otherwise check sm_lp_t for device's SM version
    sm_lp_t::combined_ver == SM_TARGET,
    sm_lp_t,
    device_launch_params_t<sm_lp_v...>
  >
> {};

//////////////// https://stackoverflow.com/a/3926854
// "false" but dependent on a template parameter so the compiler can't optimize it for static_assert()
template<typename T>
struct always_false {
    enum { value = false };
};

// Raises static (compile-time) assert when referenced
template<typename T>
struct raise_not_found_error_t {
  static_assert(always_false<T>::value, "launch_box_t could not find valid launch_params_t");
};
////////////////

// Nth sm_launch_param_t template parameter
template<typename sm_lp_t>
struct device_launch_params_t<sm_lp_t> :
std::conditional_t<
  sm_lp_t::combined_ver == SM_TARGET || sm_lp_t::combined_ver == 0,
  sm_lp_t,
  raise_not_found_error_t<void>  // Raises a compiler error
> {};

/**
 * @brief Collection of kernel launch parameters for multiple architectures
 * @tparam sm_lp_v... Pack of sm_launch_params_t types for each desired arch
 */
template<typename... sm_lp_v>
struct launch_box_t : device_launch_params_t<sm_lp_v...> {
  // Some methods to make it easy to access launch_params
};

/**
 * @brief Calculator for ratio of active to maximum warps per multiprocessor
 * @tparam launch_box_t Launch box for the corresponding kernel
 * @param kernel CUDA kernel for which to calculate the occupancy
 * \return float
 */
template<typename launch_box_t, typename func_t>
float occupancy(func_t kernel) {
  int max_active_blocks;
  int block_size = launch_box_t::block_dimensions::size;
  int device;
  cudaDeviceProp props;

  cudaGetDevice(&device);
  cudaGetDeviceProperties(&props, device);
  error::error_t status = cudaOccupancyMaxActiveBlocksPerMultiprocessor(
    &max_active_blocks,
    kernel,
    block_size,
    (size_t)0
  );
  error::throw_if_exception(status);
  float occupancy = (max_active_blocks * block_size / props.warpSize) /
                    (float)(props.maxThreadsPerMultiProcessor /
                            props.warpSize);
  return occupancy;
}

}  // namespace gunrock
}  // namespace cuda
<commit_msg>Change not found assert message<commit_after>/**
 * @file device_properties.hxx
 * @author Cameron Shinn (ctshinn@ucdavis.edu)
 * @brief
 * @version 0.1
 * @date 2020-11-09
 *
 * @copyright Copyright (c) 2020
 *
 */
#pragma once

#include <gunrock/error.hxx>

#include <type_traits>

#ifndef SM_TARGET
  #define SM_TARGET 0
#endif

namespace gunrock {
namespace cuda {

/**
 * @brief CUDA dim3 template representation, since dim3 cannot be used as a
 * template argument
 * @tparam x_ Dimension in the X direction
 * @tparam y_ Dimension in the Y direction
 * @tparam z_ Dimension in the Z direction
 */
template<unsigned int x_, unsigned int y_ = 1, unsigned int z_ = 1>
struct dim3_t {
  enum : unsigned int { x = x_, y = y_, z = z_, size = x_ * y_ * z_ };
  static dim3 get_dim3() { return dim3(x, y, z); }
};

/**
 * @brief Struct holding kernel parameters will be passed in upon launch
 * @tparam block_dimensions_ Block dimensions to launch with
 * @tparam grid_dimensions_ Grid dimensions to launch with
 * @tparam shared_memory_bytes_ Amount of shared memory to allocate
 *
 * @todo dimensions should be dim3 instead of unsigned int
 */
template<
  typename block_dimensions_,
  typename grid_dimensions_,
  unsigned int shared_memory_bytes_ = 0
>
struct launch_params_t {
  typedef block_dimensions_ block_dimensions;
  typedef grid_dimensions_ grid_dimensions;
  enum : unsigned int { shared_memory_bytes = shared_memory_bytes_ };
};

/**
 * @brief Struct holding kernel parameters for a specific SM version
 * @tparam combined_ver_ Combined major and minor compute capability version
 * @tparam block_dimensions_ Block dimensions to launch with
 * @tparam grid_dimensions_ Grid dimensions to launch with
 * @tparam shared_memory_bytes_ Amount of shared memory to allocate
 */
template<
  unsigned int combined_ver_,
  typename block_dimensions_,
  typename grid_dimensions_,
  unsigned int shared_memory_bytes_ = 0
>
struct sm_launch_params_t : launch_params_t<
                              block_dimensions_,
                              grid_dimensions_,
                              shared_memory_bytes_
                            > {
  enum : unsigned int {combined_ver = combined_ver_};
};

template<
  typename block_dimensions_,
  typename grid_dimensions_,
  unsigned int shared_memory_bytes_ = 0
>
struct fallback_launch_params_t : sm_launch_params_t<
                                    0,
                                    block_dimensions_,
                                    grid_dimensions_,
                                    shared_memory_bytes_
                                  > {};

// Easier declaration inside launch box template
template<
  typename block_dimensions_,
  typename grid_dimensions_,
  unsigned int shared_memory_bytes_ = 0
>
using fallback_t = fallback_launch_params_t<
                     block_dimensions_,
                     grid_dimensions_,
                     shared_memory_bytes_
                   >;

// Easier declaration inside launch box template
template<
  unsigned int combined_ver_,
  typename block_dimensions_,
  typename grid_dimensions_,
  unsigned int shared_memory_bytes_ = 0
>
using sm_t = sm_launch_params_t<
               combined_ver_,
               block_dimensions_,
               grid_dimensions_,
               shared_memory_bytes_
             >;

// Define named sm_launch_params_t structs for each SM version
#define SM_LAUNCH_PARAMS(combined) \
template<                                        \
  typename block_dimensions_,                    \
  typename grid_dimensions_,                     \
  unsigned int shared_memory_bytes_ = 0          \
>                                                \
using sm_##combined##_t = sm_launch_params_t<    \
                            combined,            \
                            block_dimensions_,   \
                            grid_dimensions_,    \
                            shared_memory_bytes_ \
                          >;

// Add Hopper when the SM version number becomes known (presumably 90)
SM_LAUNCH_PARAMS(86)
SM_LAUNCH_PARAMS(80)
SM_LAUNCH_PARAMS(75)
SM_LAUNCH_PARAMS(72)
SM_LAUNCH_PARAMS(70)
SM_LAUNCH_PARAMS(62)
SM_LAUNCH_PARAMS(61)
SM_LAUNCH_PARAMS(60)
SM_LAUNCH_PARAMS(53)
SM_LAUNCH_PARAMS(52)
SM_LAUNCH_PARAMS(50)
SM_LAUNCH_PARAMS(37)
SM_LAUNCH_PARAMS(35)
SM_LAUNCH_PARAMS(30)

#undef SM_LAUNCH_PARAMS

template<typename... sm_lp_v>
struct device_launch_params_t;

// 1st to (N-1)th sm_launch_param_t template parameters
template<typename sm_lp_t, typename... sm_lp_v>
struct device_launch_params_t<sm_lp_t, sm_lp_v...> :
std::conditional_t<
  sm_lp_t::combined_ver == 0,
  device_launch_params_t<sm_lp_v..., sm_lp_t>,  // If found, move fallback_launch_params_t to end of template parameter pack
  std::conditional_t<                           // Otherwise check sm_lp_t for device's SM version
    sm_lp_t::combined_ver == SM_TARGET,
    sm_lp_t,
    device_launch_params_t<sm_lp_v...>
  >
> {};

//////////////// https://stackoverflow.com/a/3926854
// "false" but dependent on a template parameter so the compiler can't optimize it for static_assert()
template<typename T>
struct always_false {
    enum { value = false };
};

// Raises static (compile-time) assert when referenced
template<typename T>
struct raise_not_found_error_t {
  static_assert(always_false<T>::value, "Launch box could not find valid launch parameters");
};
////////////////

// Nth sm_launch_param_t template parameter
template<typename sm_lp_t>
struct device_launch_params_t<sm_lp_t> :
std::conditional_t<
  sm_lp_t::combined_ver == SM_TARGET || sm_lp_t::combined_ver == 0,
  sm_lp_t,
  raise_not_found_error_t<void>  // Raises a compiler error
> {};

/**
 * @brief Collection of kernel launch parameters for multiple architectures
 * @tparam sm_lp_v... Pack of sm_launch_params_t types for each desired arch
 */
template<typename... sm_lp_v>
struct launch_box_t : device_launch_params_t<sm_lp_v...> {
  // Some methods to make it easy to access launch_params
};

/**
 * @brief Calculator for ratio of active to maximum warps per multiprocessor
 * @tparam launch_box_t Launch box for the corresponding kernel
 * @param kernel CUDA kernel for which to calculate the occupancy
 * \return float
 */
template<typename launch_box_t, typename func_t>
float occupancy(func_t kernel) {
  int max_active_blocks;
  int block_size = launch_box_t::block_dimensions::size;
  int device;
  cudaDeviceProp props;

  cudaGetDevice(&device);
  cudaGetDeviceProperties(&props, device);
  error::error_t status = cudaOccupancyMaxActiveBlocksPerMultiprocessor(
    &max_active_blocks,
    kernel,
    block_size,
    (size_t)0
  );
  error::throw_if_exception(status);
  float occupancy = (max_active_blocks * block_size / props.warpSize) /
                    (float)(props.maxThreadsPerMultiProcessor /
                            props.warpSize);
  return occupancy;
}

}  // namespace gunrock
}  // namespace cuda
<|endoftext|>


<commit_before>/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2006 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 * @endcopyright
 *
 * @file DiffSummaryReceiver.cpp
 * @brief Implementation of the class DiffSummaryReceiver
 */

#include "JNIUtil.h"
#include "EnumMapper.h"
#include "DiffSummaryReceiver.h"

DiffSummaryReceiver::DiffSummaryReceiver(jobject jreceiver)
{
    m_receiver = jreceiver;
}

DiffSummaryReceiver::~DiffSummaryReceiver()
{
    // m_receiver does not need to be destroyed, because it is a
    // parameter to the Java SVNClient.diffSummarize() method, and
    // thus not explicitly managed.
}

svn_error_t *
DiffSummaryReceiver::summarize(const svn_client_diff_summarize_t *diff,
                               void *baton,
                               apr_pool_t *pool)
{
    if (baton)
    {
        return ((DiffSummaryReceiver *) baton)->onSummary(diff, pool);
    }
    else
    {
        return SVN_NO_ERROR;
    }
}

svn_error_t *
DiffSummaryReceiver::onSummary(const svn_client_diff_summarize_t *diff,
                               apr_pool_t *pool)
{
    JNIEnv *env = JNIUtil::getEnv();
    jclass clazz;

    // As Java method IDs will not change during the time this library
    // is loaded, they can be cached.
    static jmethodID callback = 0;
    if (callback == 0)
    {
        // Initialize the method ID.
        clazz = env->FindClass(JAVA_PACKAGE "/DiffSummaryReceiver");
        if (JNIUtil::isJavaExceptionThrown())
        {
            return SVN_NO_ERROR;
        }
        callback = env->GetMethodID(clazz, "onSummary",
            "(Lorg/tigris/subversion/javahl/DiffSummary;)V");
        if (JNIUtil::isJavaExceptionThrown() || callback == 0)
        {
            return SVN_NO_ERROR;
        }
        env->DeleteLocalRef(clazz);
        if (JNIUtil::isJavaExceptionThrown())
        {
            return SVN_NO_ERROR;
        }
    }

    // Do some prep work for tranforming the DIFF parameter into a
    // Java equivalent.
    static jmethodID ctor = 0;
    clazz = env->FindClass(JAVA_PACKAGE "/DiffSummary");
    if (JNIUtil::isJavaExceptionThrown())
    {
        return SVN_NO_ERROR;
    }
    if (ctor == 0)
    {
        ctor = env->GetMethodID(clazz, "<init>",
                                "(Ljava/lang/String;IZI)V");
        if (JNIUtil::isJavaExceptionThrown() || ctor == 0)
        {
            return SVN_NO_ERROR;
        }
    }
    // Convert the arguments into their Java equivalent,
    jstring jPath = JNIUtil::makeJString(diff->path);
    if (JNIUtil::isJavaExceptionThrown())
    {
        return SVN_NO_ERROR;
    }
    jint jNodeKind = EnumMapper::mapNodeKind(diff->node_kind);
    // Actually tranform the DIFF parameter into a Java equivalent.
    jobject jDiffSummary = env->NewObject(clazz, ctor, jPath,
                                          (jint) diff->summarize_kind,
                                          (jboolean) diff->prop_changed,
                                          jNodeKind);
    if (JNIUtil::isJavaExceptionThrown() || jDiffSummary == NULL)
    {
        return SVN_NO_ERROR;
    }
    env->DeleteLocalRef(jPath);
    if(JNIUtil::isJavaExceptionThrown())
    {
        return SVN_NO_ERROR;
    }
    env->DeleteLocalRef(clazz);
    if (JNIUtil::isJavaExceptionThrown())
    {
        return SVN_NO_ERROR;
    }

    // Invoke the Java DiffSummaryReceiver callback.
    env->CallVoidMethod(m_receiver, callback, jDiffSummary);
    if (JNIUtil::isJavaExceptionThrown())
    {
        return SVN_NO_ERROR;
    }
    env->DeleteLocalRef(jDiffSummary);
    if (JNIUtil::isJavaExceptionThrown())
    {
        return SVN_NO_ERROR;
    }

    return SVN_NO_ERROR;
};
<commit_msg>Formatting tweak.<commit_after>/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2006 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 * @endcopyright
 *
 * @file DiffSummaryReceiver.cpp
 * @brief Implementation of the class DiffSummaryReceiver
 */

#include "JNIUtil.h"
#include "EnumMapper.h"
#include "DiffSummaryReceiver.h"

DiffSummaryReceiver::DiffSummaryReceiver(jobject jreceiver)
{
    m_receiver = jreceiver;
}

DiffSummaryReceiver::~DiffSummaryReceiver()
{
    // m_receiver does not need to be destroyed, because it is a
    // parameter to the Java SVNClient.diffSummarize() method, and
    // thus not explicitly managed.
}

svn_error_t *
DiffSummaryReceiver::summarize(const svn_client_diff_summarize_t *diff,
                               void *baton,
                               apr_pool_t *pool)
{
    if (baton)
    {
        return ((DiffSummaryReceiver *) baton)->onSummary(diff, pool);
    }
    else
    {
        return SVN_NO_ERROR;
    }
}

svn_error_t *
DiffSummaryReceiver::onSummary(const svn_client_diff_summarize_t *diff,
                               apr_pool_t *pool)
{
    JNIEnv *env = JNIUtil::getEnv();
    jclass clazz;

    // As Java method IDs will not change during the time this library
    // is loaded, they can be cached.
    static jmethodID callback = 0;
    if (callback == 0)
    {
        // Initialize the method ID.
        clazz = env->FindClass(JAVA_PACKAGE "/DiffSummaryReceiver");
        if (JNIUtil::isJavaExceptionThrown())
        {
            return SVN_NO_ERROR;
        }
        callback = env->GetMethodID(clazz, "onSummary",
            "(Lorg/tigris/subversion/javahl/DiffSummary;)V");
        if (JNIUtil::isJavaExceptionThrown() || callback == 0)
        {
            return SVN_NO_ERROR;
        }
        env->DeleteLocalRef(clazz);
        if (JNIUtil::isJavaExceptionThrown())
        {
            return SVN_NO_ERROR;
        }
    }

    // Do some prep work for tranforming the DIFF parameter into a
    // Java equivalent.
    static jmethodID ctor = 0;
    clazz = env->FindClass(JAVA_PACKAGE "/DiffSummary");
    if (JNIUtil::isJavaExceptionThrown())
    {
        return SVN_NO_ERROR;
    }
    if (ctor == 0)
    {
        ctor = env->GetMethodID(clazz, "<init>",
                                "(Ljava/lang/String;IZI)V");
        if (JNIUtil::isJavaExceptionThrown() || ctor == 0)
        {
            return SVN_NO_ERROR;
        }
    }
    // Convert the arguments into their Java equivalent,
    jstring jPath = JNIUtil::makeJString(diff->path);
    if (JNIUtil::isJavaExceptionThrown())
    {
        return SVN_NO_ERROR;
    }
    jint jNodeKind = EnumMapper::mapNodeKind(diff->node_kind);
    // Actually tranform the DIFF parameter into a Java equivalent.
    jobject jDiffSummary = env->NewObject(clazz, ctor, jPath,
                                          (jint) diff->summarize_kind,
                                          (jboolean) diff->prop_changed,
                                          jNodeKind);
    if (JNIUtil::isJavaExceptionThrown() || jDiffSummary == NULL)
    {
        return SVN_NO_ERROR;
    }
    env->DeleteLocalRef(jPath);
    if(JNIUtil::isJavaExceptionThrown())
    {
        return SVN_NO_ERROR;
    }
    env->DeleteLocalRef(clazz);
    if (JNIUtil::isJavaExceptionThrown())
    {
        return SVN_NO_ERROR;
    }

    // Invoke the Java DiffSummaryReceiver callback.
    env->CallVoidMethod(m_receiver, callback, jDiffSummary);
    if (JNIUtil::isJavaExceptionThrown())
    {
        return SVN_NO_ERROR;
    }
    env->DeleteLocalRef(jDiffSummary);
    if (JNIUtil::isJavaExceptionThrown())
    {
        return SVN_NO_ERROR;
    }

    return SVN_NO_ERROR;
}
<|endoftext|>


<commit_before>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"
#include "cinder/MayaCamUI.h"
#include "cinder/Sphere.h"
#include "cinder/ObjLoader.h"
#include "cinder/ImageIo.h"
#include "cinder/ip/Checkerboard.h"

#include "Resources.h"

using namespace std;
using namespace ci;
using namespace ci::app;

class TriMeshReadWriteTestApp : public App {
  public:
	void	setup() override;
	void	resize() override;

	void	mouseDown( MouseEvent event ) override;
	void	mouseDrag( MouseEvent event ) override;
	void	keyDown( KeyEvent event ) override;

	void	testObjFileWriteRead();
	void	loadObjFile( const fs::path &filePath );
	void	draw() override;

	MayaCamUI		mMayaCam;
	TriMeshRef		mMesh;
	gl::BatchRef	mBatch;
	gl::GlslProgRef	mGlsl;
	gl::TextureRef	mCheckerTexture;
};

void TriMeshReadWriteTestApp::setup()
{
	mGlsl = gl::GlslProg::create( loadAsset( "shader.vert" ), loadAsset( "shader.frag" ) );
	mGlsl->uniform( "uTex0", 0 );

	CameraPersp initialCam;
	initialCam.setPerspective( 45.0f, getWindowAspectRatio(), 0.1, 10000 );
	mMayaCam.setCurrentCam( initialCam );

	testObjFileWriteRead();

	gl::enableDepthWrite();
	gl::enableDepthRead();
}

void TriMeshReadWriteTestApp::testObjFileWriteRead()
{
	Timer t( false );

	const string modelBinName = "model.bin";

#if defined( CINDER_MSW )
	fs::path writePath = getAppPath();
#else
	fs::path writePath = getAppPath().parent_path();
#endif

	// write
	t.start();
	ObjLoader loader( loadResource( RES_8LBS_OBJ ) );
	mMesh = TriMesh::create( loader );
	t.stop();
	console() << "Reading OBJ file took " << t.getSeconds() << " seconds." << std::endl;

	if( !mMesh->hasNormals() )
		mMesh->recalculateNormals();

	t.start();
	mMesh->write( writeFile( writePath / modelBinName, false ), { geom::POSITION, geom::TEX_COORD_0 } );
	t.stop();
	console() << "Writing binary file took " << t.getSeconds() << " seconds." << std::endl;

	// read
	mMesh = TriMesh::create();

	t.start();
	mMesh->read( loadFile( writePath / modelBinName ) );
	t.stop();
	console() << "Reading binary file took " << t.getSeconds() << " seconds." << std::endl;

	if( !mMesh->hasNormals() )
		mMesh->recalculateNormals();

	mBatch = gl::Batch::create( *mMesh, mGlsl );

	mCheckerTexture = gl::Texture::create( ip::checkerboard( 512, 512, 32 ) );
	mCheckerTexture->bind( 0 );
}

void TriMeshReadWriteTestApp::resize()
{
	auto cam = mMayaCam.getCamera();
	cam.setAspectRatio( getWindowAspectRatio() );
	mMayaCam.setCurrentCam( cam );
}

void TriMeshReadWriteTestApp::mouseDown( MouseEvent event )
{
	mMayaCam.mouseDown( event.getPos() );
}

void TriMeshReadWriteTestApp::mouseDrag( MouseEvent event )
{
	mMayaCam.mouseDrag( event.getPos(), event.isLeftDown(), event.isMiddleDown(), event.isRightDown() );
}

void TriMeshReadWriteTestApp::keyDown( KeyEvent event )
{
}

void TriMeshReadWriteTestApp::draw()
{
	gl::clear( Color( 0.45f, 0.22f, 0.1f ) );

	gl::setMatrices( mMayaCam.getCamera() );

	mBatch->draw();
}

CINDER_APP( TriMeshReadWriteTestApp, RendererGl )<commit_msg>update test for MayaCamUI -> CameraUi changes<commit_after>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"
#include "cinder/CameraUi.h"
#include "cinder/Sphere.h"
#include "cinder/ObjLoader.h"
#include "cinder/ImageIo.h"
#include "cinder/ip/Checkerboard.h"

#include "Resources.h"

using namespace std;
using namespace ci;
using namespace ci::app;

class TriMeshReadWriteTestApp : public App {
  public:
	void	setup() override;
	void	resize() override;

	void	testObjFileWriteRead();
	void	loadObjFile( const fs::path &filePath );
	void	draw() override;

	CameraUi		mCamUi;
	CameraPersp		mCam;
	TriMeshRef		mMesh;
	gl::BatchRef	mBatch;
	gl::GlslProgRef	mGlsl;
	gl::TextureRef	mCheckerTexture;
};

void TriMeshReadWriteTestApp::setup()
{
	mGlsl = gl::GlslProg::create( loadAsset( "shader.vert" ), loadAsset( "shader.frag" ) );
	mGlsl->uniform( "uTex0", 0 );

	mCam.setPerspective( 45.0f, getWindowAspectRatio(), 0.1, 10000 );
	mCamUi = CameraUi( &mCam, getWindow() );

	testObjFileWriteRead();

	gl::enableDepthWrite();
	gl::enableDepthRead();
}

void TriMeshReadWriteTestApp::testObjFileWriteRead()
{
	Timer t( false );

	const string modelBinName = "model.bin";

#if defined( CINDER_MSW )
	fs::path writePath = getAppPath();
#else
	fs::path writePath = getAppPath().parent_path();
#endif

	// write
	t.start();
	ObjLoader loader( loadResource( RES_8LBS_OBJ ) );
	mMesh = TriMesh::create( loader );
	t.stop();
	console() << "Reading OBJ file took " << t.getSeconds() << " seconds." << std::endl;

	if( !mMesh->hasNormals() )
		mMesh->recalculateNormals();

	t.start();
	mMesh->write( writeFile( writePath / modelBinName, false ), { geom::POSITION, geom::TEX_COORD_0 } );
	t.stop();
	console() << "Writing binary file took " << t.getSeconds() << " seconds." << std::endl;

	// read
	mMesh = TriMesh::create();

	t.start();
	mMesh->read( loadFile( writePath / modelBinName ) );
	t.stop();
	console() << "Reading binary file took " << t.getSeconds() << " seconds." << std::endl;

	if( !mMesh->hasNormals() )
		mMesh->recalculateNormals();

	mBatch = gl::Batch::create( *mMesh, mGlsl );

	mCheckerTexture = gl::Texture::create( ip::checkerboard( 512, 512, 32 ) );
	mCheckerTexture->bind( 0 );
}

void TriMeshReadWriteTestApp::resize()
{
	mCam.setAspectRatio( getWindowAspectRatio() );
}

void TriMeshReadWriteTestApp::draw()
{
	gl::clear( Color( 0.45f, 0.22f, 0.1f ) );

	gl::setMatrices( mCam );

	mBatch->draw();
}

CINDER_APP( TriMeshReadWriteTestApp, RendererGl )<|endoftext|>


<commit_before>#include <iostream>
#include "fsmjson.h"

FSMJson::FSMJson(const char *_s)
{
	n = 0;
	bool isNull = false;
	if (_s == NULL)
	{
		n = 1;
		s = new char;
		strcpy(s, _s);
	}
	else
	{
		while (_s[n] != '\0')
		{
			n++;
		}
		n++;
		s = new char[n];
		strcpy(s, _s);
	}
	std::cout << n << std::endl;
}

FSMJson::FSMJson()
{
	n = 1;
	s = new char;
	strcpy(s, "");
}

FSMJson::~FSMJson()
{
	delete[] s;
}

FSMJson::FSMJson(FSMJson &_fsm)
{
	n = _fsm.n;
	delete[] s;
	s = new char[n];
	strcpy(s, _fsm.s);
}

char **FSMJson::FSMMatrix() const
{
	char **fsm = new char *[n - 1];
	for (int i = 0; i < n - 1; ++i)
	{
		fsm[i] = new char[n];
		for (int j = 0; j < n; ++j)
		{
			fsm[i][j] = 0;
		}
	}
	fsm[0][1] = 1;
	fsm[1][2] = 1;
	fsm[1][5] = 1;
	fsm[1][10] = 1;
	fsm[2][2] = 1;
	fsm[2][4] = 1;
	fsm[2][5] = 1;
	fsm[2][10] = 1;
	fsm[2][12] = 1;
	fsm[3][0] = 1;
	fsm[3][4] = 1;
	fsm[3][7] = 1;
	fsm[3][11] = 1;
	fsm[4][2] = 1;
	fsm[4][4] = 1;
	fsm[4][5] = 1;
	fsm[4][9] = 1;
	fsm[4][12] = 1;
	fsm[5][3] = 1;
	fsm[6][6] = 1;
	fsm[6][8] = 1;
	fsm[6][9] = 1;
	fsm[6][13] = -1;
	fsm[7][0] = 1;
	fsm[7][11] = 1;
	fsm[8][6] = 1;
	fsm[9][0] = 1;
	fsm[9][1] = 1;
	fsm[10][2] = 1;
	fsm[10][4] = 1;
	fsm[10][5] = 1;
	fsm[10][10] = 1;
	fsm[10][12] = 1;
	fsm[11][2] = 1;
	fsm[11][4] = 1;
	fsm[11][10] = 1;
	fsm[11][12] = 1;
	fsm[12][6] = 1;
	fsm[12][8] = 1;
	fsm[12][9] = 1;
	return fsm;
}

bool FSMJson::isValidJson(const char *_s1) const
{
//	char _s[] = "{\"key\":\"value\"}";
	char _s[] = "{\"key\":[{\"key\":\"oauth\",\"value\":\"1\"},{\"key\":\"method\",\"value\":\"messages.get\"}]}";
	std::cout << _s << std::endl;

	char **fsm = FSMMatrix();
	size_t size = n - 1;
	size_t i = 0;
	char mark[13] = {0, 1, 5, 0, 5, 2, 0, 0, 0, 0, 0, 3, 4};
	size_t cur_state = 0;
	size_t next_state;
	bool isKey = true; // if false - value
	bool qOpened = false; //if opened - true
	bool startState = true;
	while (_s[i] != '\0')
	{
		//определение пришедшего состояния next_state
		for (int j = 0; j < size; ++j)
		{
			if ((s[j] == _s[i]) && (mark[j] == MARK_DEF))
			{
				if ((s[j] == '[' || s[j] == '}' || s[j] == ']' || s[j] == '{' || s[j] == ',') && !isKey)
					isKey = true;
				next_state = j;
				break;
			}
			else if ((s[j] == '@') && (mark[j] == MARK_MULT))
			{
				//проверка, что s[j] - буква
				if ((_s[i] >= 65) && (_s[i] <= 90) || (_s[i] >= 97) && (_s[i] <= 122))
				{
					next_state = j;
					break;
				}
			}
			else if ((s[j] == '#') && (mark[j] == MARK_MULT))
			{
				//проверка, что s[j] - цифра
				if ((_s[i] >= 48) && (_s[i] <= 57))
				{
					next_state = j;
					break;
				}
			}
			else if ((s[j] == _s[i]) && (s[j] == '"'))
			{
				char wontState = -1;
				if (isKey)
				{
					if (!qOpened)
					{
						wontState = MARK_OPEN_Q_KEY; //я хочу состояние с такой меткой
						qOpened = true;
					}
					else
					{
						wontState = MARK_CLOSE_Q_KEY;
						qOpened = false;
						isKey = false;
					}
				}
				else
				{
					if (!qOpened)
					{
						wontState = MARK_OPEN_Q_VALUE; //я хочу состояние с такой меткой
						qOpened = true;
					}
					else
					{
						wontState = MARK_CLOSE_Q_VALUE;
						qOpened = false;
					}
				}
				if (mark[j] != wontState)
				{
					for (int k = 0; k < size; ++k)
					{
						if (mark[k] == wontState)
						{
							j = k;
							break;
						}
					}
				}
				next_state = j;
				break;
			}
		}
		//TODO проверка правильности пришедшего состояния
		if (startState)
		{
			startState = false;
			cur_state = next_state;
		}
		else
		{
			if (fsm[cur_state][next_state] == 1)
			{
				cur_state = next_state;
			}
			else
			{
				for (int k = 0; k < n - 1; ++k)
				{
					delete[] fsm[k];
				}
				delete[] fsm;
				return false;
			}
		}
		i++;
	}
	if (fsm[cur_state][size] != -1)
		return false;
	for (int i = 0; i < n - 1; ++i)
	{
		delete[] fsm[i];
	}
	delete[] fsm;
	return true;
}<commit_msg>FSM fix<commit_after>#include <iostream>
#include "fsmjson.h"

FSMJson::FSMJson(const char *_s)
{
	n = 0;
	bool isNull = false;
	if (_s == NULL)
	{
		n = 1;
		s = new char;
		strcpy(s, _s);
	}
	else
	{
		while (_s[n] != '\0')
		{
			n++;
		}
		n++;
		s = new char[n];
		strcpy(s, _s);
	}
	std::cout << n << std::endl;
}

FSMJson::FSMJson()
{
	n = 1;
	s = new char;
	strcpy(s, "");
}

FSMJson::~FSMJson()
{
	delete[] s;
}

FSMJson::FSMJson(FSMJson &_fsm)
{
	n = _fsm.n;
	delete[] s;
	s = new char[n];
	strcpy(s, _fsm.s);
}

char **FSMJson::FSMMatrix() const
{
	char **fsm = new char *[n - 1];
	for (int i = 0; i < n - 1; ++i)
	{
		fsm[i] = new char[n];
		for (int j = 0; j < n; ++j)
		{
			fsm[i][j] = 0;
		}
	}
	fsm[0][1] = 1;
	fsm[1][2] = 1;
	fsm[1][5] = 1;
	fsm[1][10] = 1;
	fsm[2][2] = 1;
	fsm[2][4] = 1;
	fsm[2][5] = 1;
	fsm[2][10] = 1;
	fsm[2][12] = 1;
	fsm[3][0] = 1;
	fsm[3][4] = 1;
	fsm[3][7] = 1;
	fsm[3][11] = 1;
	fsm[4][2] = 1;
	fsm[4][4] = 1;
	fsm[4][5] = 1;
	fsm[4][9] = 1;
	fsm[4][10] = 1;
	fsm[4][12] = 1;
	fsm[5][3] = 1;
	fsm[6][6] = 1;
	fsm[6][8] = 1;
	fsm[6][9] = 1;
	fsm[6][13] = -1;
	fsm[7][0] = 1;
	fsm[7][11] = 1;
	fsm[8][6] = 1;
	fsm[9][0] = 1;
	fsm[9][1] = 1;
	fsm[10][2] = 1;
	fsm[10][4] = 1;
	fsm[10][5] = 1;
	fsm[10][10] = 1;
	fsm[10][11] = 1;
	fsm[10][12] = 1;
	fsm[11][2] = 1;
	fsm[11][4] = 1;
	fsm[11][10] = 1;
	fsm[11][12] = 1;
	fsm[12][6] = 1;
	fsm[12][8] = 1;
	fsm[12][9] = 1;
	return fsm;
}

bool FSMJson::isValidJson(const char *_s1) const
{
//	char _s[] = "{\"key\":\"value\"}";
//	char _s[] = "{\"key\":[{\"key\":\"oauth\",\"value\":\"1\"},{\"key\":\"method\",\"value\":\"messages.get\"}]}";
	char _s[] = "{\"error\":{\"error_code\":5,\"error_msg\":\"User authorization failed invalid session.\",\"request_params\":[{\"key\":\"oauth\",\"value\":\"1\"},{\"key\":\"method\",\"value\":\"messages.get\"},{\"key\":\"out\",\"value\":\"0\"},{\"key\":\"count\",\"value\":\"1\"},{\"key\":\"user_id\",\"value\":\"9556448\"},{\"key\":\"v\",\"value\":\"5.27\"},{\"key\":\"access_token\",\"value\":\"9efd022746e646c729c3d7abed71293671aeab43ecf2675b1f9a0af19e8f1a8407ee542c3e6de10044993\"}}}";
	std::cout << _s << std::endl;

	char **fsm = FSMMatrix();
	size_t size = n - 1;
	size_t i = 0;
	char mark[13] = {0, 1, 5, 0, 5, 2, 0, 0, 0, 0, 0, 3, 4};
	size_t cur_state = 0;
	size_t next_state;
	bool isKey = true; // if false - value
	bool qOpened = false; //if opened - true
	bool startState = true;
	while (_s[i] != '\0')
	{
		//определение пришедшего состояния next_state
		for (int j = 0; j < size; ++j)
		{
			if ((s[j] == _s[i]) && (mark[j] == MARK_DEF))
			{
				if ((s[j] == '[' || s[j] == '}' || s[j] == ']' || s[j] == '{' || s[j] == ',') && !isKey)
					isKey = true;
				next_state = j;
				break;
			}
			else if ((s[j] == '@') && (mark[j] == MARK_MULT))
			{
				//проверка, что s[j] - буква
				if ((_s[i] >= 65) && (_s[i] <= 90) || (_s[i] >= 97) && (_s[i] <= 122)||(_s[i])=='_')
				{
					next_state = j;
					break;
				}
			}
			else if ((s[j] == '#') && (mark[j] == MARK_MULT))
			{
				//проверка, что s[j] - цифра
				if ((_s[i] >= 48) && (_s[i] <= 57))
				{
					next_state = j;
					break;
				}
			}
			else if ((s[j] == _s[i]) && (s[j] == '"'))
			{
				char wontState = -1;
				if (isKey)
				{
					if (!qOpened)
					{
						wontState = MARK_OPEN_Q_KEY; //я хочу состояние с такой меткой
						qOpened = true;
					}
					else
					{
						wontState = MARK_CLOSE_Q_KEY;
						qOpened = false;
						isKey = false;
					}
				}
				else
				{
					if (!qOpened)
					{
						wontState = MARK_OPEN_Q_VALUE; //я хочу состояние с такой меткой
						qOpened = true;
					}
					else
					{
						wontState = MARK_CLOSE_Q_VALUE;
						qOpened = false;
					}
				}
				if (mark[j] != wontState)
				{
					for (int k = 0; k < size; ++k)
					{
						if (mark[k] == wontState)
						{
							j = k;
							break;
						}
					}
				}
				next_state = j;
				break;
			}
		}
		//TODO проверка правильности пришедшего состояния
		if (startState)
		{
			startState = false;
			cur_state = next_state;
		}
		else
		{
			if (fsm[cur_state][next_state] == 1)
			{
				cur_state = next_state;
			}
			else
			{
				for (int k = 0; k < n - 1; ++k)
				{
					delete[] fsm[k];
				}
				delete[] fsm;
				return false;
			}
		}
		i++;
	}
	if (fsm[cur_state][size] != -1)
		return false;
	for (int i = 0; i < n - 1; ++i)
	{
		delete[] fsm[i];
	}
	delete[] fsm;
	return true;
}<|endoftext|>


<commit_before>// Copyright Andrew Resch 2008. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <libtorrent/ip_filter.hpp>
#include <boost/python.hpp>
#include "gil.hpp"

using namespace boost::python;
using namespace libtorrent;

namespace
{
    void add_rule(ip_filter& filter, std::string start, std::string end, int flags)
    {
        return filter.add_rule(address::from_string(start), address::from_string(end), flags);
    }

    int _access(ip_filter& filter, std::string addr)
    {
        return filter.access(address::from_string(addr));
    }
}

void bind_ip_filter()
{
    class_<ip_filter>("ip_filter")
        .def("add_rule", add_rule)
        .def("access", _access)
        .def("export_filter", allow_threads(&ip_filter::export_filter))
    ;
}

<commit_msg>Fix building in windows<commit_after>// Copyright Andrew Resch 2008. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <libtorrent/ip_filter.hpp>
#include <boost/python.hpp>
#include "gil.hpp"

using namespace boost::python;
using namespace libtorrent;

namespace
{
    void add_rule(ip_filter& filter, std::string start, std::string end, int flags)
    {
        return filter.add_rule(address::from_string(start), address::from_string(end), flags);
    }

    int access0(ip_filter& filter, std::string addr)
    {
        return filter.access(address::from_string(addr));
    }
}

void bind_ip_filter()
{
    class_<ip_filter>("ip_filter")
        .def("add_rule", add_rule)
        .def("access", access0)
        .def("export_filter", allow_threads(&ip_filter::export_filter))
    ;
}
<|endoftext|>


<commit_before><commit_msg>coverity#707933 Uninitialized scalar field<commit_after><|endoftext|>


<commit_before>/**
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

#include <aws/core/auth/AWSCredentialsProvider.h>

#include <aws/core/config/AWSProfileConfigLoader.h>
#include <aws/core/platform/Environment.h>
#include <aws/core/platform/FileSystem.h>
#include <aws/core/platform/OSVersionInfo.h>
#include <aws/core/utils/logging/LogMacros.h>
#include <aws/core/utils/StringUtils.h>
#include <aws/core/utils/json/JsonSerializer.h>
#include <aws/core/utils/FileSystemUtils.h>
#include <aws/core/client/AWSError.h>
#include <aws/core/utils/StringUtils.h>
#include <aws/core/utils/xml/XmlSerializer.h>
#include <cstdlib>
#include <fstream>
#include <string.h>
#include <climits>

using namespace Aws::Utils;
using namespace Aws::Utils::Logging;
using namespace Aws::Auth;
using namespace Aws::Internal;
using namespace Aws::FileSystem;
using namespace Aws::Utils::Xml;
using namespace Aws::Client;
using Aws::Utils::Threading::ReaderLockGuard;
using Aws::Utils::Threading::WriterLockGuard;

static const char ACCESS_KEY_ENV_VAR[] = "AWS_ACCESS_KEY_ID";
static const char SECRET_KEY_ENV_VAR[] = "AWS_SECRET_ACCESS_KEY";
static const char SESSION_TOKEN_ENV_VAR[] = "AWS_SESSION_TOKEN";
static const char DEFAULT_PROFILE[] = "default";
static const char AWS_PROFILE_ENV_VAR[] = "AWS_PROFILE";
static const char AWS_PROFILE_DEFAULT_ENV_VAR[] = "AWS_DEFAULT_PROFILE";

static const char AWS_CREDENTIALS_FILE[] = "AWS_SHARED_CREDENTIALS_FILE";
extern const char AWS_CONFIG_FILE[] = "AWS_CONFIG_FILE";

extern const char PROFILE_DIRECTORY[] = ".aws";
static const char DEFAULT_CREDENTIALS_FILE[] = "credentials";
extern const char DEFAULT_CONFIG_FILE[] = "config";

static const int EXPIRATION_GRACE_PERIOD = 5 * 1000;

void AWSCredentialsProvider::Reload()
{
    m_lastLoadedMs = DateTime::Now().Millis();
}

bool AWSCredentialsProvider::IsTimeToRefresh(long reloadFrequency)
{
    if (DateTime::Now().Millis() - m_lastLoadedMs > reloadFrequency)
    {
        return true;
    }
    return false;
}

static const char* ENVIRONMENT_LOG_TAG = "EnvironmentAWSCredentialsProvider";

AWSCredentials EnvironmentAWSCredentialsProvider::GetAWSCredentials()
{
    auto accessKey = Aws::Environment::GetEnv(ACCESS_KEY_ENV_VAR);
    AWSCredentials credentials;

    if (!accessKey.empty())
    {
        credentials.SetAWSAccessKeyId(accessKey);

        AWS_LOGSTREAM_DEBUG(ENVIRONMENT_LOG_TAG, "Found credential in environment with access key id " << accessKey);
        auto secretKey = Aws::Environment::GetEnv(SECRET_KEY_ENV_VAR);

        if (!secretKey.empty())
        {
            credentials.SetAWSSecretKey(secretKey);
            AWS_LOGSTREAM_INFO(ENVIRONMENT_LOG_TAG, "Found secret key");
        }

        auto sessionToken = Aws::Environment::GetEnv(SESSION_TOKEN_ENV_VAR);

        if(!sessionToken.empty())
        {
            credentials.SetSessionToken(sessionToken);
            AWS_LOGSTREAM_INFO(ENVIRONMENT_LOG_TAG, "Found sessionToken");
        }
    }

    return credentials;
}

Aws::String Aws::Auth::GetConfigProfileFilename()
{
    auto configFileNameFromVar = Aws::Environment::GetEnv(AWS_CONFIG_FILE);
    if (!configFileNameFromVar.empty())
    {
        return configFileNameFromVar;
    }
    else
    {
        return Aws::FileSystem::GetHomeDirectory() + PROFILE_DIRECTORY + PATH_DELIM + DEFAULT_CONFIG_FILE;
    }
}

Aws::String Aws::Auth::GetConfigProfileName()
{
    auto profileFromVar = Aws::Environment::GetEnv(AWS_PROFILE_DEFAULT_ENV_VAR);
    if (profileFromVar.empty())
    {
        profileFromVar = Aws::Environment::GetEnv(AWS_PROFILE_ENV_VAR);
    }

    if (profileFromVar.empty())
    {
        return Aws::String(DEFAULT_PROFILE);
    }
    else
    {
        return profileFromVar;
    }
}

static const char* PROFILE_LOG_TAG = "ProfileConfigFileAWSCredentialsProvider";

Aws::String ProfileConfigFileAWSCredentialsProvider::GetCredentialsProfileFilename()
{
    auto credentialsFileNameFromVar = Aws::Environment::GetEnv(AWS_CREDENTIALS_FILE);

    if (credentialsFileNameFromVar.empty())
    {
        return Aws::FileSystem::GetHomeDirectory() + PROFILE_DIRECTORY + PATH_DELIM + DEFAULT_CREDENTIALS_FILE;
    }
    else
    {
        return credentialsFileNameFromVar;
    }
}

Aws::String ProfileConfigFileAWSCredentialsProvider::GetProfileDirectory()
{
    Aws::String credentialsFileName = GetCredentialsProfileFilename();
    auto lastSeparator = credentialsFileName.find_last_of(PATH_DELIM);
    if (lastSeparator != std::string::npos)
    {
        return credentialsFileName.substr(0, lastSeparator);
    }
    else
    {
        return {};
    }
}

ProfileConfigFileAWSCredentialsProvider::ProfileConfigFileAWSCredentialsProvider(long refreshRateMs) :
    m_profileToUse(Aws::Auth::GetConfigProfileName()),
    m_credentialsFileLoader(GetCredentialsProfileFilename()),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(PROFILE_LOG_TAG, "Setting provider to read credentials from " <<  GetCredentialsProfileFilename() << " for credentials file"
                                      << " and " <<  GetConfigProfileFilename() << " for the config file "
                                      << ", for use with profile " << m_profileToUse);
}

ProfileConfigFileAWSCredentialsProvider::ProfileConfigFileAWSCredentialsProvider(const char* profile, long refreshRateMs) :
    m_profileToUse(profile),
    m_credentialsFileLoader(GetCredentialsProfileFilename()),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(PROFILE_LOG_TAG, "Setting provider to read credentials from " <<  GetCredentialsProfileFilename() << " for credentials file"
                                      << " and " <<  GetConfigProfileFilename() << " for the config file "
                                      << ", for use with profile " << m_profileToUse);
}

AWSCredentials ProfileConfigFileAWSCredentialsProvider::GetAWSCredentials()
{
    RefreshIfExpired();
    ReaderLockGuard guard(m_reloadLock);
    auto credsFileProfileIter = m_credentialsFileLoader.GetProfiles().find(m_profileToUse);

    if(credsFileProfileIter != m_credentialsFileLoader.GetProfiles().end())
    {
        return credsFileProfileIter->second.GetCredentials();
    }

    return AWSCredentials();
}

void ProfileConfigFileAWSCredentialsProvider::Reload()
{
    m_credentialsFileLoader.Load();
    AWSCredentialsProvider::Reload();
}

void ProfileConfigFileAWSCredentialsProvider::RefreshIfExpired()
{
    ReaderLockGuard guard(m_reloadLock);
    if (!IsTimeToRefresh(m_loadFrequencyMs))
    {
       return;
    }

    guard.UpgradeToWriterLock();
    if (!IsTimeToRefresh(m_loadFrequencyMs)) // double-checked lock to avoid refreshing twice
    {
        return;
    }

    Reload();
}

static const char* INSTANCE_LOG_TAG = "InstanceProfileCredentialsProvider";

InstanceProfileCredentialsProvider::InstanceProfileCredentialsProvider(long refreshRateMs) :
    m_ec2MetadataConfigLoader(Aws::MakeShared<Aws::Config::EC2InstanceProfileConfigLoader>(INSTANCE_LOG_TAG)),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Creating Instance with default EC2MetadataClient and refresh rate " << refreshRateMs);
}

InstanceProfileCredentialsProvider::InstanceProfileCredentialsProvider(const std::shared_ptr<Aws::Config::EC2InstanceProfileConfigLoader>& loader, long refreshRateMs) :
    m_ec2MetadataConfigLoader(loader),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Creating Instance with injected EC2MetadataClient and refresh rate " << refreshRateMs);
}

AWSCredentials InstanceProfileCredentialsProvider::GetAWSCredentials()
{
    RefreshIfExpired();
    ReaderLockGuard guard(m_reloadLock);
    auto profileIter = m_ec2MetadataConfigLoader->GetProfiles().find(Aws::Config::INSTANCE_PROFILE_KEY);

    if(profileIter != m_ec2MetadataConfigLoader->GetProfiles().end())
    {
        return profileIter->second.GetCredentials();
    }

    return AWSCredentials();
}

void InstanceProfileCredentialsProvider::Reload()
{
    AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Credentials have expired attempting to repull from EC2 Metadata Service.");
    m_ec2MetadataConfigLoader->Load();
    AWSCredentialsProvider::Reload();
}

void InstanceProfileCredentialsProvider::RefreshIfExpired()
{
    AWS_LOGSTREAM_DEBUG(INSTANCE_LOG_TAG, "Checking if latest credential pull has expired.");
    ReaderLockGuard guard(m_reloadLock);
    if (!IsTimeToRefresh(m_loadFrequencyMs))
    {
        return;
    }

    guard.UpgradeToWriterLock();
    if (!IsTimeToRefresh(m_loadFrequencyMs)) // double-checked lock to avoid refreshing twice
    {
        return;
    }
    Reload();
}

static const char TASK_ROLE_LOG_TAG[] = "TaskRoleCredentialsProvider";

TaskRoleCredentialsProvider::TaskRoleCredentialsProvider(const char* URI, long refreshRateMs) :
    m_ecsCredentialsClient(Aws::MakeShared<Aws::Internal::ECSCredentialsClient>(TASK_ROLE_LOG_TAG, URI)),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Creating TaskRole with default ECSCredentialsClient and refresh rate " << refreshRateMs);
}

TaskRoleCredentialsProvider::TaskRoleCredentialsProvider(const char* endpoint, const char* token, long refreshRateMs) :
    m_ecsCredentialsClient(Aws::MakeShared<Aws::Internal::ECSCredentialsClient>(TASK_ROLE_LOG_TAG, ""/*resourcePath*/, endpoint, token)),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Creating TaskRole with default ECSCredentialsClient and refresh rate " << refreshRateMs);
}

TaskRoleCredentialsProvider::TaskRoleCredentialsProvider(
        const std::shared_ptr<Aws::Internal::ECSCredentialsClient>& client, long refreshRateMs) :
    m_ecsCredentialsClient(client),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Creating TaskRole with default ECSCredentialsClient and refresh rate " << refreshRateMs);
}

AWSCredentials TaskRoleCredentialsProvider::GetAWSCredentials()
{
    RefreshIfExpired();
    ReaderLockGuard guard(m_reloadLock);
    return m_credentials;
}

bool TaskRoleCredentialsProvider::ExpiresSoon() const
{
    return ((m_credentials.GetExpiration() - Aws::Utils::DateTime::Now()).count() < EXPIRATION_GRACE_PERIOD);
}

void TaskRoleCredentialsProvider::Reload()
{
    AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Credentials have expired or will expire, attempting to repull from ECS IAM Service.");

    auto credentialsStr = m_ecsCredentialsClient->GetECSCredentials();
    if (credentialsStr.empty()) return;

    Json::JsonValue credentialsDoc(credentialsStr);
    if (!credentialsDoc.WasParseSuccessful())
    {
        AWS_LOGSTREAM_ERROR(TASK_ROLE_LOG_TAG, "Failed to parse output from ECSCredentialService.");
        return;
    }

    Aws::String accessKey, secretKey, token;
    Utils::Json::JsonView credentialsView(credentialsDoc);
    accessKey = credentialsView.GetString("AccessKeyId");
    secretKey = credentialsView.GetString("SecretAccessKey");
    token = credentialsView.GetString("Token");
    AWS_LOGSTREAM_DEBUG(TASK_ROLE_LOG_TAG, "Successfully pulled credentials from metadata service with access key " << accessKey);

    m_credentials.SetAWSAccessKeyId(accessKey);
    m_credentials.SetAWSSecretKey(secretKey);
    m_credentials.SetSessionToken(token);
    m_credentials.SetExpiration(Aws::Utils::DateTime(credentialsView.GetString("Expiration"), DateFormat::ISO_8601));
    AWSCredentialsProvider::Reload();
}

void TaskRoleCredentialsProvider::RefreshIfExpired()
{
    AWS_LOGSTREAM_DEBUG(TASK_ROLE_LOG_TAG, "Checking if latest credential pull has expired.");
    ReaderLockGuard guard(m_reloadLock);
    if (!m_credentials.IsEmpty() && !IsTimeToRefresh(m_loadFrequencyMs) && !ExpiresSoon())
    {
        return;
    }

    guard.UpgradeToWriterLock();

    if (!m_credentials.IsEmpty() && !IsTimeToRefresh(m_loadFrequencyMs) && !ExpiresSoon())
    {
        return;
    }

    Reload();
}

static const char PROCESS_LOG_TAG[] = "ProcessCredentialsProvider";
ProcessCredentialsProvider::ProcessCredentialsProvider() :
    m_profileToUse(Aws::Auth::GetConfigProfileName())
{
    AWS_LOGSTREAM_INFO(PROCESS_LOG_TAG, "Setting process credentials provider to read config from " <<  m_profileToUse);
}

ProcessCredentialsProvider::ProcessCredentialsProvider(const Aws::String& profile) :
    m_profileToUse(profile)
{
    AWS_LOGSTREAM_INFO(PROCESS_LOG_TAG, "Setting process credentials provider to read config from " <<  m_profileToUse);
}

AWSCredentials ProcessCredentialsProvider::GetAWSCredentials()
{
    RefreshIfExpired();
    ReaderLockGuard guard(m_reloadLock);
    return m_credentials;
}

void ProcessCredentialsProvider::Reload()
{
    auto profile = Aws::Config::GetCachedConfigProfile(m_profileToUse);
    const Aws::String &command = profile.GetCredentialProcess();
    if (command.empty())
    {
        AWS_LOGSTREAM_ERROR(PROCESS_LOG_TAG, "Failed to find credential process's profile: " << m_profileToUse);
        return;
    }
    m_credentials = GetCredentialsFromProcess(command);
}

void ProcessCredentialsProvider::RefreshIfExpired()
{
    ReaderLockGuard guard(m_reloadLock);
    if (!m_credentials.IsExpiredOrEmpty())
    {
       return;
    }

    guard.UpgradeToWriterLock();
    if (!m_credentials.IsExpiredOrEmpty()) // double-checked lock to avoid refreshing twice
    {
        return;
    }

    Reload();
}

AWSCredentials Aws::Auth::GetCredentialsFromProcess(const Aws::String& process)
{
    Aws::String command = process;
    command.append(" 2>&1"); // redirect stderr to stdout
    Aws::String result = Aws::Utils::StringUtils::Trim(Aws::OSVersionInfo::GetSysCommandOutput(command.c_str()).c_str());
    Json::JsonValue credentialsDoc(result);
    if (!credentialsDoc.WasParseSuccessful())
    {
        AWS_LOGSTREAM_ERROR(PROFILE_LOG_TAG, "Failed to load credential from running: " << command << " Error: " << result);
        return {};
    }

    Aws::Utils::Json::JsonView credentialsView(credentialsDoc);
    if (!credentialsView.KeyExists("Version") || credentialsView.GetInteger("Version") != 1)
    {
        AWS_LOGSTREAM_ERROR(PROFILE_LOG_TAG, "Encountered an unsupported process credentials payload version:" << credentialsView.GetInteger("Version"));
        return {};
    }

    AWSCredentials credentials;
    Aws::String accessKey, secretKey, token, expire;
    if (credentialsView.KeyExists("AccessKeyId"))
    {
        credentials.SetAWSAccessKeyId(credentialsView.GetString("AccessKeyId"));
    }

    if (credentialsView.KeyExists("SecretAccessKey"))
    {
        credentials.SetAWSSecretKey(credentialsView.GetString("SecretAccessKey"));
    }

    if (credentialsView.KeyExists("SessionToken"))
    {
        credentials.SetSessionToken(credentialsView.GetString("SessionToken"));
    }

    if (credentialsView.KeyExists("Expiration"))
    {
        const auto expiration = Aws::Utils::DateTime(credentialsView.GetString("Expiration"), DateFormat::ISO_8601);
        if (expiration.WasParseSuccessful())
        {
            credentials.SetExpiration(expiration);
        }
        else
        {
            AWS_LOGSTREAM_ERROR(PROFILE_LOG_TAG, "Failed to parse credential's expiration value as an ISO 8601 Date. Credentials will be marked expired.");
            credentials.SetExpiration(Aws::Utils::DateTime::Now());
        }
    }
    else
    {
        credentials.SetExpiration((std::chrono::time_point<std::chrono::system_clock>::max)());
    }

    AWS_LOGSTREAM_DEBUG(PROFILE_LOG_TAG, "Successfully pulled credentials from process credential with AccessKey: " << accessKey << ", Expiration:" << credentialsView.GetString("Expiration"));
    return credentials;
}

<commit_msg>changed log level of the retry failure message (#744)<commit_after>/**
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

#include <aws/core/auth/AWSCredentialsProvider.h>

#include <aws/core/config/AWSProfileConfigLoader.h>
#include <aws/core/platform/Environment.h>
#include <aws/core/platform/FileSystem.h>
#include <aws/core/platform/OSVersionInfo.h>
#include <aws/core/utils/logging/LogMacros.h>
#include <aws/core/utils/StringUtils.h>
#include <aws/core/utils/json/JsonSerializer.h>
#include <aws/core/utils/FileSystemUtils.h>
#include <aws/core/client/AWSError.h>
#include <aws/core/utils/StringUtils.h>
#include <aws/core/utils/xml/XmlSerializer.h>
#include <cstdlib>
#include <fstream>
#include <string.h>
#include <climits>

using namespace Aws::Utils;
using namespace Aws::Utils::Logging;
using namespace Aws::Auth;
using namespace Aws::Internal;
using namespace Aws::FileSystem;
using namespace Aws::Utils::Xml;
using namespace Aws::Client;
using Aws::Utils::Threading::ReaderLockGuard;
using Aws::Utils::Threading::WriterLockGuard;

static const char ACCESS_KEY_ENV_VAR[] = "AWS_ACCESS_KEY_ID";
static const char SECRET_KEY_ENV_VAR[] = "AWS_SECRET_ACCESS_KEY";
static const char SESSION_TOKEN_ENV_VAR[] = "AWS_SESSION_TOKEN";
static const char DEFAULT_PROFILE[] = "default";
static const char AWS_PROFILE_ENV_VAR[] = "AWS_PROFILE";
static const char AWS_PROFILE_DEFAULT_ENV_VAR[] = "AWS_DEFAULT_PROFILE";

static const char AWS_CREDENTIALS_FILE[] = "AWS_SHARED_CREDENTIALS_FILE";
extern const char AWS_CONFIG_FILE[] = "AWS_CONFIG_FILE";

extern const char PROFILE_DIRECTORY[] = ".aws";
static const char DEFAULT_CREDENTIALS_FILE[] = "credentials";
extern const char DEFAULT_CONFIG_FILE[] = "config";

static const int EXPIRATION_GRACE_PERIOD = 5 * 1000;

void AWSCredentialsProvider::Reload()
{
    m_lastLoadedMs = DateTime::Now().Millis();
}

bool AWSCredentialsProvider::IsTimeToRefresh(long reloadFrequency)
{
    if (DateTime::Now().Millis() - m_lastLoadedMs > reloadFrequency)
    {
        return true;
    }
    return false;
}

static const char* ENVIRONMENT_LOG_TAG = "EnvironmentAWSCredentialsProvider";

AWSCredentials EnvironmentAWSCredentialsProvider::GetAWSCredentials()
{
    auto accessKey = Aws::Environment::GetEnv(ACCESS_KEY_ENV_VAR);
    AWSCredentials credentials;

    if (!accessKey.empty())
    {
        credentials.SetAWSAccessKeyId(accessKey);

        AWS_LOGSTREAM_DEBUG(ENVIRONMENT_LOG_TAG, "Found credential in environment with access key id " << accessKey);
        auto secretKey = Aws::Environment::GetEnv(SECRET_KEY_ENV_VAR);

        if (!secretKey.empty())
        {
            credentials.SetAWSSecretKey(secretKey);
            AWS_LOGSTREAM_INFO(ENVIRONMENT_LOG_TAG, "Found secret key");
        }

        auto sessionToken = Aws::Environment::GetEnv(SESSION_TOKEN_ENV_VAR);

        if(!sessionToken.empty())
        {
            credentials.SetSessionToken(sessionToken);
            AWS_LOGSTREAM_INFO(ENVIRONMENT_LOG_TAG, "Found sessionToken");
        }
    }

    return credentials;
}

Aws::String Aws::Auth::GetConfigProfileFilename()
{
    auto configFileNameFromVar = Aws::Environment::GetEnv(AWS_CONFIG_FILE);
    if (!configFileNameFromVar.empty())
    {
        return configFileNameFromVar;
    }
    else
    {
        return Aws::FileSystem::GetHomeDirectory() + PROFILE_DIRECTORY + PATH_DELIM + DEFAULT_CONFIG_FILE;
    }
}

Aws::String Aws::Auth::GetConfigProfileName()
{
    auto profileFromVar = Aws::Environment::GetEnv(AWS_PROFILE_DEFAULT_ENV_VAR);
    if (profileFromVar.empty())
    {
        profileFromVar = Aws::Environment::GetEnv(AWS_PROFILE_ENV_VAR);
    }

    if (profileFromVar.empty())
    {
        return Aws::String(DEFAULT_PROFILE);
    }
    else
    {
        return profileFromVar;
    }
}

static const char* PROFILE_LOG_TAG = "ProfileConfigFileAWSCredentialsProvider";

Aws::String ProfileConfigFileAWSCredentialsProvider::GetCredentialsProfileFilename()
{
    auto credentialsFileNameFromVar = Aws::Environment::GetEnv(AWS_CREDENTIALS_FILE);

    if (credentialsFileNameFromVar.empty())
    {
        return Aws::FileSystem::GetHomeDirectory() + PROFILE_DIRECTORY + PATH_DELIM + DEFAULT_CREDENTIALS_FILE;
    }
    else
    {
        return credentialsFileNameFromVar;
    }
}

Aws::String ProfileConfigFileAWSCredentialsProvider::GetProfileDirectory()
{
    Aws::String credentialsFileName = GetCredentialsProfileFilename();
    auto lastSeparator = credentialsFileName.find_last_of(PATH_DELIM);
    if (lastSeparator != std::string::npos)
    {
        return credentialsFileName.substr(0, lastSeparator);
    }
    else
    {
        return {};
    }
}

ProfileConfigFileAWSCredentialsProvider::ProfileConfigFileAWSCredentialsProvider(long refreshRateMs) :
    m_profileToUse(Aws::Auth::GetConfigProfileName()),
    m_credentialsFileLoader(GetCredentialsProfileFilename()),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(PROFILE_LOG_TAG, "Setting provider to read credentials from " <<  GetCredentialsProfileFilename() << " for credentials file"
                                      << " and " <<  GetConfigProfileFilename() << " for the config file "
                                      << ", for use with profile " << m_profileToUse);
}

ProfileConfigFileAWSCredentialsProvider::ProfileConfigFileAWSCredentialsProvider(const char* profile, long refreshRateMs) :
    m_profileToUse(profile),
    m_credentialsFileLoader(GetCredentialsProfileFilename()),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(PROFILE_LOG_TAG, "Setting provider to read credentials from " <<  GetCredentialsProfileFilename() << " for credentials file"
                                      << " and " <<  GetConfigProfileFilename() << " for the config file "
                                      << ", for use with profile " << m_profileToUse);
}

AWSCredentials ProfileConfigFileAWSCredentialsProvider::GetAWSCredentials()
{
    RefreshIfExpired();
    ReaderLockGuard guard(m_reloadLock);
    auto credsFileProfileIter = m_credentialsFileLoader.GetProfiles().find(m_profileToUse);

    if(credsFileProfileIter != m_credentialsFileLoader.GetProfiles().end())
    {
        return credsFileProfileIter->second.GetCredentials();
    }

    return AWSCredentials();
}

void ProfileConfigFileAWSCredentialsProvider::Reload()
{
    m_credentialsFileLoader.Load();
    AWSCredentialsProvider::Reload();
}

void ProfileConfigFileAWSCredentialsProvider::RefreshIfExpired()
{
    ReaderLockGuard guard(m_reloadLock);
    if (!IsTimeToRefresh(m_loadFrequencyMs))
    {
       return;
    }

    guard.UpgradeToWriterLock();
    if (!IsTimeToRefresh(m_loadFrequencyMs)) // double-checked lock to avoid refreshing twice
    {
        return;
    }

    Reload();
}

static const char* INSTANCE_LOG_TAG = "InstanceProfileCredentialsProvider";

InstanceProfileCredentialsProvider::InstanceProfileCredentialsProvider(long refreshRateMs) :
    m_ec2MetadataConfigLoader(Aws::MakeShared<Aws::Config::EC2InstanceProfileConfigLoader>(INSTANCE_LOG_TAG)),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Creating Instance with default EC2MetadataClient and refresh rate " << refreshRateMs);
}

InstanceProfileCredentialsProvider::InstanceProfileCredentialsProvider(const std::shared_ptr<Aws::Config::EC2InstanceProfileConfigLoader>& loader, long refreshRateMs) :
    m_ec2MetadataConfigLoader(loader),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Creating Instance with injected EC2MetadataClient and refresh rate " << refreshRateMs);
}

AWSCredentials InstanceProfileCredentialsProvider::GetAWSCredentials()
{
    RefreshIfExpired();
    ReaderLockGuard guard(m_reloadLock);
    auto profileIter = m_ec2MetadataConfigLoader->GetProfiles().find(Aws::Config::INSTANCE_PROFILE_KEY);

    if(profileIter != m_ec2MetadataConfigLoader->GetProfiles().end())
    {
        return profileIter->second.GetCredentials();
    }

    return AWSCredentials();
}

void InstanceProfileCredentialsProvider::Reload()
{
    AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Credentials have expired attempting to repull from EC2 Metadata Service.");
    m_ec2MetadataConfigLoader->Load();
    AWSCredentialsProvider::Reload();
}

void InstanceProfileCredentialsProvider::RefreshIfExpired()
{
    AWS_LOGSTREAM_DEBUG(INSTANCE_LOG_TAG, "Checking if latest credential pull has expired.");
    ReaderLockGuard guard(m_reloadLock);
    if (!IsTimeToRefresh(m_loadFrequencyMs))
    {
        return;
    }

    guard.UpgradeToWriterLock();
    if (!IsTimeToRefresh(m_loadFrequencyMs)) // double-checked lock to avoid refreshing twice
    {
        return;
    }
    Reload();
}

static const char TASK_ROLE_LOG_TAG[] = "TaskRoleCredentialsProvider";

TaskRoleCredentialsProvider::TaskRoleCredentialsProvider(const char* URI, long refreshRateMs) :
    m_ecsCredentialsClient(Aws::MakeShared<Aws::Internal::ECSCredentialsClient>(TASK_ROLE_LOG_TAG, URI)),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Creating TaskRole with default ECSCredentialsClient and refresh rate " << refreshRateMs);
}

TaskRoleCredentialsProvider::TaskRoleCredentialsProvider(const char* endpoint, const char* token, long refreshRateMs) :
    m_ecsCredentialsClient(Aws::MakeShared<Aws::Internal::ECSCredentialsClient>(TASK_ROLE_LOG_TAG, ""/*resourcePath*/, endpoint, token)),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Creating TaskRole with default ECSCredentialsClient and refresh rate " << refreshRateMs);
}

TaskRoleCredentialsProvider::TaskRoleCredentialsProvider(
        const std::shared_ptr<Aws::Internal::ECSCredentialsClient>& client, long refreshRateMs) :
    m_ecsCredentialsClient(client),
    m_loadFrequencyMs(refreshRateMs)
{
    AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Creating TaskRole with default ECSCredentialsClient and refresh rate " << refreshRateMs);
}

AWSCredentials TaskRoleCredentialsProvider::GetAWSCredentials()
{
    RefreshIfExpired();
    ReaderLockGuard guard(m_reloadLock);
    return m_credentials;
}

bool TaskRoleCredentialsProvider::ExpiresSoon() const
{
    return ((m_credentials.GetExpiration() - Aws::Utils::DateTime::Now()).count() < EXPIRATION_GRACE_PERIOD);
}

void TaskRoleCredentialsProvider::Reload()
{
    AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Credentials have expired or will expire, attempting to repull from ECS IAM Service.");

    auto credentialsStr = m_ecsCredentialsClient->GetECSCredentials();
    if (credentialsStr.empty()) return;

    Json::JsonValue credentialsDoc(credentialsStr);
    if (!credentialsDoc.WasParseSuccessful())
    {
        AWS_LOGSTREAM_ERROR(TASK_ROLE_LOG_TAG, "Failed to parse output from ECSCredentialService.");
        return;
    }

    Aws::String accessKey, secretKey, token;
    Utils::Json::JsonView credentialsView(credentialsDoc);
    accessKey = credentialsView.GetString("AccessKeyId");
    secretKey = credentialsView.GetString("SecretAccessKey");
    token = credentialsView.GetString("Token");
    AWS_LOGSTREAM_DEBUG(TASK_ROLE_LOG_TAG, "Successfully pulled credentials from metadata service with access key " << accessKey);

    m_credentials.SetAWSAccessKeyId(accessKey);
    m_credentials.SetAWSSecretKey(secretKey);
    m_credentials.SetSessionToken(token);
    m_credentials.SetExpiration(Aws::Utils::DateTime(credentialsView.GetString("Expiration"), DateFormat::ISO_8601));
    AWSCredentialsProvider::Reload();
}

void TaskRoleCredentialsProvider::RefreshIfExpired()
{
    AWS_LOGSTREAM_DEBUG(TASK_ROLE_LOG_TAG, "Checking if latest credential pull has expired.");
    ReaderLockGuard guard(m_reloadLock);
    if (!m_credentials.IsEmpty() && !IsTimeToRefresh(m_loadFrequencyMs) && !ExpiresSoon())
    {
        return;
    }

    guard.UpgradeToWriterLock();

    if (!m_credentials.IsEmpty() && !IsTimeToRefresh(m_loadFrequencyMs) && !ExpiresSoon())
    {
        return;
    }

    Reload();
}

static const char PROCESS_LOG_TAG[] = "ProcessCredentialsProvider";
ProcessCredentialsProvider::ProcessCredentialsProvider() :
    m_profileToUse(Aws::Auth::GetConfigProfileName())
{
    AWS_LOGSTREAM_INFO(PROCESS_LOG_TAG, "Setting process credentials provider to read config from " <<  m_profileToUse);
}

ProcessCredentialsProvider::ProcessCredentialsProvider(const Aws::String& profile) :
    m_profileToUse(profile)
{
    AWS_LOGSTREAM_INFO(PROCESS_LOG_TAG, "Setting process credentials provider to read config from " <<  m_profileToUse);
}

AWSCredentials ProcessCredentialsProvider::GetAWSCredentials()
{
    RefreshIfExpired();
    ReaderLockGuard guard(m_reloadLock);
    return m_credentials;
}

void ProcessCredentialsProvider::Reload()
{
    auto profile = Aws::Config::GetCachedConfigProfile(m_profileToUse);
    const Aws::String &command = profile.GetCredentialProcess();
    if (command.empty())
    {
        AWS_LOGSTREAM_INFO(PROCESS_LOG_TAG, "Failed to find credential process's profile: " << m_profileToUse);
        return;
    }
    m_credentials = GetCredentialsFromProcess(command);
}

void ProcessCredentialsProvider::RefreshIfExpired()
{
    ReaderLockGuard guard(m_reloadLock);
    if (!m_credentials.IsExpiredOrEmpty())
    {
       return;
    }

    guard.UpgradeToWriterLock();
    if (!m_credentials.IsExpiredOrEmpty()) // double-checked lock to avoid refreshing twice
    {
        return;
    }

    Reload();
}

AWSCredentials Aws::Auth::GetCredentialsFromProcess(const Aws::String& process)
{
    Aws::String command = process;
    command.append(" 2>&1"); // redirect stderr to stdout
    Aws::String result = Aws::Utils::StringUtils::Trim(Aws::OSVersionInfo::GetSysCommandOutput(command.c_str()).c_str());
    Json::JsonValue credentialsDoc(result);
    if (!credentialsDoc.WasParseSuccessful())
    {
        AWS_LOGSTREAM_ERROR(PROFILE_LOG_TAG, "Failed to load credential from running: " << command << " Error: " << result);
        return {};
    }

    Aws::Utils::Json::JsonView credentialsView(credentialsDoc);
    if (!credentialsView.KeyExists("Version") || credentialsView.GetInteger("Version") != 1)
    {
        AWS_LOGSTREAM_ERROR(PROFILE_LOG_TAG, "Encountered an unsupported process credentials payload version:" << credentialsView.GetInteger("Version"));
        return {};
    }

    AWSCredentials credentials;
    Aws::String accessKey, secretKey, token, expire;
    if (credentialsView.KeyExists("AccessKeyId"))
    {
        credentials.SetAWSAccessKeyId(credentialsView.GetString("AccessKeyId"));
    }

    if (credentialsView.KeyExists("SecretAccessKey"))
    {
        credentials.SetAWSSecretKey(credentialsView.GetString("SecretAccessKey"));
    }

    if (credentialsView.KeyExists("SessionToken"))
    {
        credentials.SetSessionToken(credentialsView.GetString("SessionToken"));
    }

    if (credentialsView.KeyExists("Expiration"))
    {
        const auto expiration = Aws::Utils::DateTime(credentialsView.GetString("Expiration"), DateFormat::ISO_8601);
        if (expiration.WasParseSuccessful())
        {
            credentials.SetExpiration(expiration);
        }
        else
        {
            AWS_LOGSTREAM_ERROR(PROFILE_LOG_TAG, "Failed to parse credential's expiration value as an ISO 8601 Date. Credentials will be marked expired.");
            credentials.SetExpiration(Aws::Utils::DateTime::Now());
        }
    }
    else
    {
        credentials.SetExpiration((std::chrono::time_point<std::chrono::system_clock>::max)());
    }

    AWS_LOGSTREAM_DEBUG(PROFILE_LOG_TAG, "Successfully pulled credentials from process credential with AccessKey: " << accessKey << ", Expiration:" << credentialsView.GetString("Expiration"));
    return credentials;
}

<|endoftext|>