szaszm commented on a change in pull request #1264:
URL: https://github.com/apache/nifi-minifi-cpp/pull/1264#discussion_r808569132



##########
File path: extensions/expression-language/Expression.cpp
##########
@@ -636,7 +636,7 @@ Value expr_toDate(const std::vector<Value> &args) {
   auto utc = date::locate_zone("UTC");
   auto utct = date::make_zoned(utc, t);
   auto zt = date::make_zoned(zone, utct.get_local_time());
-  return 
Value(std::chrono::duration_cast<std::chrono::milliseconds>(zt.get_sys_time().time_since_epoch()).count());
+  return 
Value(int64_t{std::chrono::duration_cast<std::chrono::milliseconds>(zt.get_sys_time().time_since_epoch()).count()});

Review comment:
       With libc++, the count return value is `long long`, which is not 
convertible to `int64_t` (alias to `long`). `Value` doesn't have a `long long` 
constructor, so I had to add a non-narrowing cast to these places.

##########
File path: extensions/bustache/ApplyTemplate.cpp
##########
@@ -19,81 +19,76 @@
  */
 #include "ApplyTemplate.h"
 
-#include <iostream>
+#include <filesystem>
 #include <fstream>
+#include <iostream>
 #include <memory>
-#include <set>
 #include <string>
-
-#include <boost/iostreams/device/mapped_file.hpp>
-
-#include <bustache/model.hpp>
+#include <utility>
 
 #include "core/Resource.h"
+#include "bustache/model.hpp"
+
+namespace org::apache::nifi::minifi::processors {
+
+const core::Property ApplyTemplate::Template("Template", "Path to the input 
mustache template file", "");
+const core::Relationship ApplyTemplate::Success("success", "success 
operational on the flow record");
+
+namespace {
+class WriteCallback : public OutputStreamCallback {
+ public:
+  WriteCallback(std::filesystem::path templateFile, const core::FlowFile& 
flow_file)
+      :template_file_{std::move(templateFile)}, 
flow_file_{std::move(flow_file)}
+  {}
+  int64_t process(const std::shared_ptr<io::BaseStream>& stream) override {
+    logger_->log_info("ApplyTemplate reading template file from %s", 
template_file_);
+    // TODO(szaszm): we might want to return to memory-mapped input files when 
the next todo is done. Until then, the agents stores the whole result in memory 
anyway, so no point in not doing the same
+    // with the template file itself
+    const auto template_file_contents = [this] {
+      std::ifstream ifs{template_file_};
+      return std::string{std::istreambuf_iterator<char>{ifs}, 
std::istreambuf_iterator<char>{}};
+    }();
+
+    bustache::format format(template_file_contents);
+    bustache::object data;
+
+    for (const auto &attr : flow_file_.getAttributes()) {
+      data[attr.first] = attr.second;
+    }
+
+    // TODO(calebj) write ostream reciever for format() to prevent excessive 
copying
+    std::string ostring = to_string(format(data));
+    stream->write(gsl::make_span(ostring).as_span<const std::byte>());
+    return gsl::narrow<int64_t>(ostring.length());
+  }
 
-namespace org {
-namespace apache {
-namespace nifi {
-namespace minifi {
-namespace processors {
-
-core::Property ApplyTemplate::Template("Template", "Path to the input mustache 
template file", "");
-core::Relationship ApplyTemplate::Success("success", "success operational on 
the flow record");
+ private:
+  std::shared_ptr<core::logging::Logger> logger_ = 
core::logging::LoggerFactory<ApplyTemplate>::getLogger();
+  std::filesystem::path template_file_;
+  const core::FlowFile& flow_file_;
+};
+}  // namespace
 
 void ApplyTemplate::initialize() {
-  //! Set the supported properties
-  std::set<core::Property> properties;
-  properties.insert(Template);
-  setSupportedProperties(properties);
-  //! Set the supported relationships
-  std::set<core::Relationship> relationships;
-  relationships.insert(Success);
-  setSupportedRelationships(relationships);
+  setSupportedProperties({Template});
+  setSupportedRelationships({Success});
 }
 
 void ApplyTemplate::onTrigger(const std::shared_ptr<core::ProcessContext> 
&context,
                               const std::shared_ptr<core::ProcessSession> 
&session) {
   auto flow_file = session->get();
-
   if (!flow_file) {
     return;
   }
 
   std::string template_file;
   context->getProperty(Template, template_file, flow_file);
-  WriteCallback cb(template_file, flow_file);
+  WriteCallback cb(template_file, *flow_file);
   session->write(flow_file, &cb);
   session->transfer(flow_file, Success);
 }
 
-ApplyTemplate::WriteCallback::WriteCallback(const std::string &path, const 
std::shared_ptr<core::FlowFile> &flow_file) {
-  template_file_ = path;
-  flow_file_ = flow_file;
-}
-
-int64_t ApplyTemplate::WriteCallback::process(const 
std::shared_ptr<io::BaseStream>& stream) {
-  logger_->log_info("ApplyTemplate reading template file from %s", 
template_file_);
-  boost::iostreams::mapped_file_source file(template_file_);

Review comment:
       This line was crashing (segfault) when compiled with libc++, so I 
removed it. I also saw a bunch of refactoring opportunities, so ApplyTemplate 
has quite a few changes. As it turns out, this line was the only reason the 
bustache extension required boost, so I removed that requirement and checked a 
few boost-related pieces of code.

##########
File path: libminifi/include/utils/OptionalUtils.h
##########
@@ -43,22 +43,19 @@ struct is_optional<std::optional<T>, void> : std::true_type 
{};
 namespace detail {
 // map implementation
 template<typename SourceType, typename F>
-auto operator|(const std::optional<SourceType>& o, map_wrapper<F> f) 
noexcept(noexcept(std::invoke(std::forward<F>(f.function), *o)))
-    -> std::optional<typename 
std::decay<decltype(std::invoke(std::forward<F>(f.function), *o))>::type> {
-  if (o.has_value()) {
-    return std::make_optional(std::invoke(std::forward<F>(f.function), *o));
+auto operator|(std::optional<SourceType> o, map_wrapper<F> f) 
noexcept(noexcept(std::invoke(std::forward<F>(f.function), *std::move(o)))) {
+  using cb_result = std::decay_t<std::invoke_result_t<F, SourceType>>;
+  if constexpr(std::is_same_v<cb_result, void>) {

Review comment:
       Added support for `void` return types from the callback, in which case 
`map` just returns `void`. There is no such thing as `optional<void>`. This 
simplified the change in `GetFile`.

##########
File path: extensions/standard-processors/processors/GetFile.cpp
##########
@@ -133,7 +130,9 @@ void GetFile::onSchedule(core::ProcessContext *context, 
core::ProcessSessionFact
     core::Property::StringToInt(value, request_.minSize);
   }
 
-  context->getProperty(PollInterval.getName(), request_.pollInterval);
+  context->getProperty<core::TimePeriodValue>(PollInterval)
+      | utils::map(&core::TimePeriodValue::getMilliseconds)
+      | utils::map([this](std::chrono::milliseconds ms) { 
request_.pollInterval = ms; });

Review comment:
       ```
   In file included from 
/home/szaszm/nifi-minifi-cpp-3/extensions/standard-processors/processors/GetFile.cpp:18:
   In file included from 
/home/szaszm/nifi-minifi-cpp-3/extensions/standard-processors/processors/GetFile.h:29:
   In file included from 
/home/szaszm/nifi-minifi-cpp-3/extensions/standard-processors/../../libminifi/include/core/Processor.h:39:
   
/home/szaszm/nifi-minifi-cpp-3/extensions/standard-processors/../../libminifi/include/core/ConfigurableComponent.h:237:15:
 error: no matching conversion for static_cast from 'const 
org::apache::nifi::minifi::core::PropertyValue' to 'std::chrono::duration<long 
long, std::ratio<1, 1000>>'
         value = static_cast<T>(property.getValue());  // cast throws if the 
value is invalid
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   
/home/szaszm/nifi-minifi-cpp-3/extensions/standard-processors/../../libminifi/include/core/ProcessorNode.h:73:30:
 note: in instantiation of function template specialization 
'org::apache::nifi::minifi::core::ConfigurableComponent::getProperty<std::chrono::duration<long
 long, std::ratio<1, 1000>>>' requested here
         return processor_cast->getProperty<T>(name, value);
                                ^
   
/home/szaszm/nifi-minifi-cpp-3/extensions/standard-processors/../../libminifi/include/core/ProcessContext.h:386:29:
 note: in instantiation of function template specialization 
'org::apache::nifi::minifi::core::ProcessorNode::getProperty<std::chrono::duration<long
 long, std::ratio<1, 1000>>>' requested here
       return processor_node_->getProperty<typename 
std::common_type<T>::type>(name, value);
                               ^
   
/home/szaszm/nifi-minifi-cpp-3/extensions/standard-processors/../../libminifi/include/core/ProcessContext.h:118:12:
 note: in instantiation of function template specialization 
'org::apache::nifi::minifi::core::ProcessContext::getPropertyImp<std::chrono::duration<long
 long, std::ratio<1, 1000>>>' requested here
       return getPropertyImp<typename std::common_type<T>::type>(name, value);
              ^
   
/home/szaszm/nifi-minifi-cpp-3/extensions/standard-processors/processors/GetFile.cpp:136:12:
 note: in instantiation of function template specialization 
'org::apache::nifi::minifi::core::ProcessContext::getProperty<std::chrono::duration<long
 long, std::ratio<1, 1000>>>' requested here
     context->getProperty(PollInterval.getName(), request_.pollInterval);
              ^
   /usr/include/c++/v1/chrono:1023:28: note: candidate constructor (the 
implicit copy constructor) not viable: no known conversion from 'const 
org::apache::nifi::minifi::core::PropertyValue' to 'const 
std::chrono::duration<long long, std::ratio<1, 1000>>' for 1st argument
   class _LIBCPP_TEMPLATE_VIS duration
                              ^
   /usr/include/c++/v1/chrono:1023:28: note: candidate constructor (the 
implicit move constructor) not viable: no known conversion from 'const 
org::apache::nifi::minifi::core::PropertyValue' to 'std::chrono::duration<long 
long, std::ratio<1, 1000>>' for 1st argument
   /usr/include/c++/v1/chrono:1075:18: note: candidate template ignored: 
requirement 'is_convertible<org::apache::nifi::minifi::core::PropertyValue, 
long long>::value' was not satisfied [with _Rep2 = 
org::apache::nifi::minifi::core::PropertyValue]
           explicit duration(const _Rep2& __r,
                    ^
   /usr/include/c++/v1/chrono:1087:9: note: candidate template ignored: could 
not match 'duration<type-parameter-0-0, type-parameter-0-1>' against 'const 
org::apache::nifi::minifi::core::PropertyValue'
           duration(const duration<_Rep2, _Period2>& __d,
           ^
   /usr/include/c++/v1/chrono:1068:9: note: candidate constructor not viable: 
requires 0 arguments, but 1 was provided
           duration() = default;
           ^
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to