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



##########
File path: libminifi/include/FlowController.h
##########
@@ -87,13 +91,8 @@ class FlowController : public 
core::controller::ForwardingControllerServiceProvi
     return this->provenance_repo_;
   }
 
-  // Get the flowfile repository
-  virtual std::shared_ptr<core::Repository> getFlowFileRepository() {
-    return this->flow_file_repo_;
-  }
-
   // Load flow xml from disk, after that, create the root process group and 
its children, initialize the flows
-  virtual void load(const std::shared_ptr<core::ProcessGroup> &root = nullptr, 
bool reload = false);
+  virtual void load(std::unique_ptr<core::ProcessGroup>&& root = nullptr, bool 
reload = false);

Review comment:
       Pass the pointer by value instead of rvalue reference. Since it's 
move-only, the usage will be the same, but the implementation will have to move 
out from the parameter. It's not a big deal, though, we might even save some 
time by moving twice, but without an extra level of indirection.

##########
File path: libminifi/include/core/state/nodes/QueueMetrics.h
##########
@@ -57,16 +57,16 @@ class QueueMetrics : public ResponseNode {
     return "QueueMetrics";
   }
 
-  void addConnection(const std::shared_ptr<minifi::Connection> &connection) {
+  void addConnection(std::unique_ptr<minifi::Connection>&& connection) {

Review comment:
       Consider pass-by-value for unique_ptr's. They are not too expensive to 
move.
   More details, if you're interested: https://youtu.be/rHIkrotSwcc?t=1050

##########
File path: libminifi/src/core/ProcessSession.cpp
##########
@@ -1034,14 +1030,18 @@ void ProcessSession::ensureNonNullResourceClaim(
 }
 
 std::shared_ptr<core::FlowFile> ProcessSession::get() {
-  std::shared_ptr<Connectable> first = 
process_context_->getProcessorNode()->pickIncomingConnection();
+  const auto first = 
process_context_->getProcessorNode()->pickIncomingConnection();
 
   if (first == nullptr) {
     logger_->log_trace("Get is null for %s", 
process_context_->getProcessorNode()->getName());
     return nullptr;
   }
 
-  std::shared_ptr<Connection> current = 
std::static_pointer_cast<Connection>(first);
+  auto current = dynamic_cast<Connection*>(first);
+  if (!current) {
+    logger_->log_error("Get could not find current Connection for %s", 
process_context_->getProcessorNode()->getName());

Review comment:
       I suggest a more detailed error message:
   ```suggestion
       logger_->log_error("The incoming connection [%s] of the processor [%s] 
\"%s\" is not actually a Connection.",
           first->getUUIDStr(), 
process_context_->getProcessorNode()->getUUIDStr(), 
process_context_->getProcessorNode()->getName());
   ```

##########
File path: libminifi/src/core/ProcessGroup.cpp
##########
@@ -91,33 +91,16 @@ ProcessGroup::~ProcessGroup() {
   }
 }
 
-bool ProcessGroup::isRootProcessGroup() {
-  return (type_ == ROOT_PROCESS_GROUP);
-}
-
 bool ProcessGroup::isRemoteProcessGroup() {
   return (type_ == REMOTE_PROCESS_GROUP);
 }
 
 
-void ProcessGroup::addProcessor(const std::shared_ptr<Processor>& processor) {
+void ProcessGroup::addProcessor(std::unique_ptr<Processor>&& processor) {

Review comment:
       Consider pass-by-value and a precondition to check that it's not null

##########
File path: libminifi/include/utils/GeneralUtils.h
##########
@@ -34,6 +34,16 @@ constexpr T intdiv_ceil(T numerator, T denominator) {
       : numerator / denominator + (numerator % denominator != 0));
 }
 
+/**
+ * safely converts unique_ptr from one type to another
+ * if conversion succeeds, an desired valid unique_ptr is returned, the "from" 
object released and invalidated
+ * if conversion fails, an empty unique_ptr is returned
+ */
+template <typename T_To, typename T_From>
+std::unique_ptr<T_To> dynamic_unique_cast(std::unique_ptr<T_From>&& obj) {

Review comment:
       I think it would be cleaner semantics to pass-by-value. This would mean 
that we release the object regardless of the success of the cast, which is a 
downside, but reading the client code will be simpler, because when we see 
passing with `std::move`, we know that the old object WILL be null.

##########
File path: libminifi/src/core/Connectable.cpp
##########
@@ -141,39 +141,37 @@ void Connectable::notifyWork() {
   }
 }
 
-std::set<std::shared_ptr<Connectable>> 
Connectable::getOutGoingConnections(const std::string &relationship) const {
-  std::set<std::shared_ptr<Connectable>> empty;
-
-  const auto &&it = out_going_connections_.find(relationship);
-  if (it != out_going_connections_.end()) {
+std::set<Connectable*> Connectable::getOutGoingConnections(const std::string 
&relationship) const {
+  const auto &&it = outgoing_connections_.find(relationship);

Review comment:
       Would you mind removing the `&&`? This only works because of temporary 
lifetime extension, but there is no reason why we wouldn't just store the 
iterator by value like normal.

##########
File path: libminifi/include/processors/ProcessorUtils.h
##########
@@ -47,10 +45,10 @@ class ProcessorUtils {
       if (ptr == nullptr) {
         ptr = 
core::ClassLoader::getDefaultClassLoader().instantiate("ExecuteJavaClass", 
uuid);
         if (ptr != nullptr) {
-          std::shared_ptr<core::Processor> processor = 
std::dynamic_pointer_cast<core::Processor>(ptr);
-          if (processor == nullptr) {
+          if (dynamic_cast<core::Processor*>(ptr.get()) == nullptr) {
             throw std::runtime_error("Invalid return from the classloader");
           }
+          auto processor = 
std::unique_ptr<core::Processor>{dynamic_cast<core::Processor*>(ptr.release())};

Review comment:
       Use the dynamic unique cast utility here as well.

##########
File path: libminifi/include/processors/ProcessorUtils.h
##########
@@ -61,25 +59,15 @@ class ProcessorUtils {
     if (ptr == nullptr) {
       return nullptr;
     }
-    auto returnPtr = std::dynamic_pointer_cast<core::Processor>(ptr);
-
-    if (returnPtr == nullptr) {
+    if (dynamic_cast<core::Processor*>(ptr.get()) == nullptr) {
       throw std::runtime_error("Invalid return from the classloader");
     }
 
+    auto returnPtr = 
std::unique_ptr<core::Processor>{dynamic_cast<core::Processor*>(ptr.release())};

Review comment:
       and here.
   ```suggestion
       auto returnPtr = 
utils::dynamic_unique_cast<core::Processor>(std::move(ptr));
       if (!returnPtr) {
         throw std::runtime_error("Invalid return from the classloader");
       }
   ```

##########
File path: libminifi/src/FlowController.cpp
##########
@@ -271,7 +271,7 @@ std::unique_ptr<core::ProcessGroup> 
FlowController::loadInitialFlow() {
   return root;
 }
 
-void FlowController::load(const std::shared_ptr<core::ProcessGroup> &root, 
bool reload) {
+void FlowController::load(std::unique_ptr<core::ProcessGroup>&& root, bool 
reload) {

Review comment:
       Consider pass-by-value

##########
File path: libminifi/src/c2/C2Client.cpp
##########
@@ -115,7 +116,8 @@ void 
C2Client::initialize(core::controller::ControllerServiceProvider *controlle
         flowMonitor->setFlowVersion(flow_configuration_->getFlowVersion());
       }
       std::lock_guard<std::mutex> guard(metrics_mutex_);
-      root_response_nodes_[response_node->getName()] = response_node;
+      std::unique_ptr<state::response::ResponseNode> 
responseNodeToStore{dynamic_cast<state::response::ResponseNode*>(instance.release())};

Review comment:
       use `utils::dynamic_unique_cast`
   
   Whenever `release()` is called on a unique_ptr, it requires extra attention. 
Just by looking around for `release()` in our codebase, I found a memory leak 
(in the openwsman extension). I find this separation of the check (line 91) and 
the release (here) to be very error-prone.




-- 
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: issues-unsubscr...@nifi.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to