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]