"Plugin (un)used" post reload notification

Most of the plugins is assumed to use per-plugin-instance data-structures
when reloading their configs and only a few of them that wish to optimize
performance or deal with the complexities of using per-plugin DSO "global"
data-structures would use plugin configuration reload notifications like
`TSRemapPreConfigReload` and `TSRemapPostConfigReload`.

Instead of trying to foresee the needs or the expectations of each use-case,
a more "open-ended" and straight-forward design was chosen for the configuration
reload notifications. The notifications are broadcasted to all loaded plugins
at the moments before and after the reload attempt, regardless of whether
a plugin is part of the new configuration or not.

During the `TSRemapPostConfigReload` we already decided to notify the
plugin if the plugin reload was successful or not so the plugins can
recover adequately in case of configuration reload failure.

This change adds a signal to show if the particular plugin was part of
the new configuration. This will be beneficial for use-cases that expect
plugin reload notification not to be called in case they are not part of
the new configuration so they can ignore the notification.

This change also attempts to clarify related documentation and code
comments as well.
diff --git a/doc/developer-guide/api/functions/TSRemap.en.rst b/doc/developer-guide/api/functions/TSRemap.en.rst
index bbfc220..0e8ad4e 100644
--- a/doc/developer-guide/api/functions/TSRemap.en.rst
+++ b/doc/developer-guide/api/functions/TSRemap.en.rst
@@ -72,8 +72,10 @@
 
 :func:`TSRemapPostConfigReload` is called to indicate the end of the the new remap configuration
 load. It is called on the newly and previously loaded plugins, invoked by the new, current and
-previous still used configurations. It also indicates if the configuration reload was successful
-by passing :macro:`TS_SUCCESS` or :macro:`TS_ERROR`. This is an optional entry point.
+previous still used configurations. It also indicates wheather the configuration reload was successful
+by passing :macro:`TSREMAP_CONFIG_RELOAD_FAILURE` in case of failure and to notify the plugins if they
+are going to be part of the new configuration by passing :macro:`TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED`
+or :macro:`TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED`. This is an optional entry point.
 
 Generally speaking, calls to these functions are mutually exclusive. The exception
 is for functions which take an HTTP transaction as a parameter. Calls to these
@@ -111,6 +113,20 @@
         The remapping attempt in general failed and the transaction should fail with an
         error return to the user agent.
 
+.. type:: TSRemapReloadStatus
+
+    .. macro:: TSREMAP_CONFIG_RELOAD_FAILURE
+
+        Notify the plugin that configuration parsing failed.
+
+    .. macro:: TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED
+
+        Configuration parsing succeeded and plugin was used by the new configuration.
+
+    .. macro:: TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED
+
+        Configuration parsing succeeded but plugin was NOT used by the new configuration.
+
 Return Values
 =============
 
diff --git a/doc/developer-guide/plugins/remap-plugins.en.rst b/doc/developer-guide/plugins/remap-plugins.en.rst
index ead70b2..d436169 100644
--- a/doc/developer-guide/plugins/remap-plugins.en.rst
+++ b/doc/developer-guide/plugins/remap-plugins.en.rst
@@ -80,8 +80,9 @@
 available when the rule is actually matched. In particular the plugin arguments will not be
 available.
 
-Calls to :func:`TSRemapNewInstance` are serialized. All calls to :func:`TSRemapNewInstance`
-for a given configuration will be called and completed before any calls to :func:`TSRemapDoRemap`.
+Calls to :func:`TSRemapNewInstance` are guaranteed to be serialized. All calls to
+:func:`TSRemapNewInstance` for a given new configuration are guaranteed to be called and
+completed before any calls to :func:`TSRemapDoRemap`.
 
 If there is an error then the callback should return :macro:`TS_ERROR` and fill in the
 :arg:`errbuff` with a C-string describing the error. Otherwise the function must return
@@ -91,18 +92,30 @@
 Configuration reload notifications
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+Most of the plugins is assumed to use per-plugin-instance data-structures when reloading their
+configs and only a few of them that wish to optimize performance or deal with the complexities
+of using a per-plugin DSO "global" data-structures would use pluging configuration reload
+notifications like :func:`TSRemapPreConfigReload` and :func:`TSRemapPostConfigReload`.
+
+Instead of trying to foresee the needs or the expectations of each use-case, a more "open-ended"
+and straight-forward design was chosen for the configuration reload notifications.
+The notifications are broadcasted to all loaded plugins at the moments before and after 
+the reload attempt, regardless of whether a plugin is part of the new configuration or not.
+
 :func:`TSRemapPreConfigReload` is called *before* the parsing of a new remap configuration starts
 to notify plugins of the coming configuration reload. It is called on all already loaded plugins,
 invoked by current and all previous still used configurations. This is an optional entry point.
 
 :func:`TSRemapPostConfigReload` is called to indicate the end of the the new remap configuration
 load. It is called on the newly and previously loaded plugins, invoked by the new, current and
-previous still used configurations. It also indicates if the configuration reload was successful
-by passing :macro:`TS_SUCCESS` or :macro:`TS_ERROR`. This is an optional entry point.
+previous still used configurations. It also indicates wheather the configuration reload was successful
+by passing :macro:`TSREMAP_CONFIG_RELOAD_FAILURE` in case of failure and to notify the plugins if they
+are going to be part of the new configuration by passing :macro:`TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED`
+or :macro:`TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED`. This is an optional entry point.
 
 These calls are called per *plugin*, not per invocation of the plugin in :file:`remap.config`
-and only will be called if the plugin was called at least once with :func:`TSRemapNewInstance`
-for any configuration and at least one configuration using it is still loaded.
+and only will be called if the plugin was instantianted by at least one configuration loaded
+after the traffic server started and at least one configuration using it is still loaded.
 
 :func:`TSRemapPreConfigReload` will be called serially for all loaded plugins
 before any call to :func:`TSRemapNewInstance` during parsing of the new configuration.
@@ -115,9 +128,10 @@
 per plugin data structures. These structures can be created (or updated) as needed
 when a plugin invocation instance is loaded (:func:`TSRemapNewInstance` is called).
 Then it could be used in subsequent invocation instances loading. After the configuration
-reload is done :func:`TSRemapPostConfigReload` could be used to confirm
-the data structures update if :macro:`TS_SUCCESS` is passed or recover / clean-up
-after a failed reload attempt if :macro:`TS_ERROR` is passed.
+reload is done :func:`TSRemapPostConfigReload` could be used to confirm the data
+structures update if reload was successful, recover / clean-up after a failed
+reload attempt, or if so wishes to ignore the notification if plugin is not part
+of the new configuration..
 
 
 Runtime
diff --git a/include/ts/remap.h b/include/ts/remap.h
index dd7be38..1e804b9 100644
--- a/include/ts/remap.h
+++ b/include/ts/remap.h
@@ -75,6 +75,16 @@
   TSREMAP_ERROR = -1 /* Some error, that should generate an error page */
 } TSRemapStatus;
 
+/* Status code passed to the plugin by TSRemapPostConfigReload() signaling
+ * (1) if the configuration reload was successful and
+ * (2) if (1) is successful show if the plugin was part of the new configuration */
+typedef enum {
+  TSREMAP_CONFIG_RELOAD_FAILURE             = 0, /* notify the plugin that configuration parsing failed */
+  TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED = 1, /* configuration parsing succeeded and plugin was used by the new configuration */
+  TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED =
+    2 /* configuration parsing succeeded but plugin was NOT used by the new configuration */
+} TSRemapReloadStatus;
+
 /* ----------------------------------------------------------------------------------
    These are the entry points a plugin can implement. Note that TSRemapInit() and
    TSRemapDoRemap() are both required.
@@ -108,7 +118,7 @@
                           TS_ERROR - (re)load failed.
    Return: none
 */
-tsapi void TSRemapPostConfigReload(TSReturnCode reloadStatus);
+tsapi void TSRemapPostConfigReload(TSRemapReloadStatus reloadStatus);
 
 /* Remap new request
    Mandatory interface function.
diff --git a/proxy/http/remap/PluginDso.h b/proxy/http/remap/PluginDso.h
index 23a84b5..e542718 100644
--- a/proxy/http/remap/PluginDso.h
+++ b/proxy/http/remap/PluginDso.h
@@ -34,6 +34,7 @@
 #include <ctime>
 
 #include "ts/apidefs.h"
+#include "ts/remap.h"
 #include "tscore/ts_file.h"
 namespace fs = ts::file;
 
@@ -75,10 +76,10 @@
   using PluginList = ts::IntrusiveDList<PluginDso::Linkage>;
 
   /* Methods to be called when processing a list of plugins, to be overloaded by the remap or the global plugins correspondingly */
-  virtual void indicatePreReload()                           = 0;
-  virtual void indicatePostReload(TSReturnCode reloadStatus) = 0;
-  virtual bool init(std::string &error)                      = 0;
-  virtual void done()                                        = 0;
+  virtual void indicatePreReload()                                  = 0;
+  virtual void indicatePostReload(TSRemapReloadStatus reloadStatus) = 0;
+  virtual bool init(std::string &error)                             = 0;
+  virtual void done()                                               = 0;
 
   void acquire();
   void release();
diff --git a/proxy/http/remap/PluginFactory.cc b/proxy/http/remap/PluginFactory.cc
index 8b045cc..9491228 100644
--- a/proxy/http/remap/PluginFactory.cc
+++ b/proxy/http/remap/PluginFactory.cc
@@ -22,6 +22,8 @@
 
  */
 
+#include <unordered_map>
+
 #include "RemapPluginInfo.h"
 #include "PluginFactory.h"
 #ifdef PLUGIN_DSO_TESTS
@@ -274,13 +276,25 @@
  * @brief Tell all plugins (that so wish) that remap.config is done reloading
  */
 void
-PluginFactory::indicatePostReload(TSReturnCode reloadStatus)
+PluginFactory::indicatePostReload(bool reloadSuccessful)
 {
   Debug(_tag, "indicated config is done reloading by factory '%s' to %zu plugin%s", getUuid(), _list.count(),
         _list.count() != 1 ? "s" : "");
 
-  for (auto it = _list.begin(); _list.end() != it; it++) {
-    it->indicatePostReload(reloadStatus);
+  /* Find out which plugins (DSO) are actually instantiated by this factory */
+  std::unordered_map<PluginDso *, int> pluginUsed;
+  for (auto &inst : _instList) {
+    pluginUsed[&(inst._plugin)]++;
+  }
+
+  for (auto &plugin : _list) {
+    TSRemapReloadStatus status = TSREMAP_CONFIG_RELOAD_FAILURE;
+    if (reloadSuccessful) {
+      /* reload succeeded but was the plugin instantiated by this factory? */
+      status = (pluginUsed.end() == pluginUsed.find(&plugin) ? TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED :
+                                                               TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED);
+    }
+    plugin.indicatePostReload(status);
   }
 }
 
diff --git a/proxy/http/remap/PluginFactory.h b/proxy/http/remap/PluginFactory.h
index db722bd..5982db4 100644
--- a/proxy/http/remap/PluginFactory.h
+++ b/proxy/http/remap/PluginFactory.h
@@ -102,7 +102,7 @@
 
   void deactivate();
   void indicatePreReload();
-  void indicatePostReload(TSReturnCode reloadStatus);
+  void indicatePostReload(bool reloadSuccessful);
 
 protected:
   PluginDso *findByEffectivePath(const fs::path &path);
diff --git a/proxy/http/remap/RemapConfig.cc b/proxy/http/remap/RemapConfig.cc
index 5774b18..424f4bf 100644
--- a/proxy/http/remap/RemapConfig.cc
+++ b/proxy/http/remap/RemapConfig.cc
@@ -1329,7 +1329,7 @@
 
   /* Now after we parsed the configuration and (re)loaded plugins and plugin instances
    * accordingly notify all plugins that we are done */
-  rewrite->pluginFactory.indicatePostReload(status ? TS_SUCCESS : TS_ERROR);
+  rewrite->pluginFactory.indicatePostReload(status);
 
   return status;
 }
diff --git a/proxy/http/remap/RemapPluginInfo.cc b/proxy/http/remap/RemapPluginInfo.cc
index a98c3ee..8f8962b 100644
--- a/proxy/http/remap/RemapPluginInfo.cc
+++ b/proxy/http/remap/RemapPluginInfo.cc
@@ -258,7 +258,7 @@
 }
 
 void
-RemapPluginInfo::indicatePostReload(TSReturnCode reloadStatus)
+RemapPluginInfo::indicatePostReload(TSRemapReloadStatus reloadStatus)
 {
   setPluginContext();
 
diff --git a/proxy/http/remap/RemapPluginInfo.h b/proxy/http/remap/RemapPluginInfo.h
index 731196a..6d06b45 100644
--- a/proxy/http/remap/RemapPluginInfo.h
+++ b/proxy/http/remap/RemapPluginInfo.h
@@ -57,7 +57,7 @@
   /// Reload function, called to inform the plugin that configuration is going to be reloaded.
   using PreReload_F = void();
   /// Reload function, called to inform the plugin that configuration is done reloading.
-  using PostReload_F = void(TSReturnCode);
+  using PostReload_F = void(TSRemapReloadStatus);
   /// Called when remapping for a transaction has finished.
   using Done_F = void();
   /// Create an rule instance.
@@ -99,7 +99,7 @@
 
   /* Used by traffic server core to indicate configuration reload */
   virtual void indicatePreReload();
-  virtual void indicatePostReload(TSReturnCode reloadStatus);
+  virtual void indicatePostReload(TSRemapReloadStatus reloadStatus);
 
 protected:
   /* Utility to be used only with unit testing */
diff --git a/proxy/http/remap/unit-tests/plugin_testing_calls.cc b/proxy/http/remap/unit-tests/plugin_testing_calls.cc
index 1d57da3..883b971 100644
--- a/proxy/http/remap/unit-tests/plugin_testing_calls.cc
+++ b/proxy/http/remap/unit-tests/plugin_testing_calls.cc
@@ -109,10 +109,10 @@
 }
 
 void
-TSRemapPostConfigReload(TSReturnCode reloadStatus)
+TSRemapPostConfigReload(TSRemapReloadStatus reloadStatus)
 {
   debugObject.postReloadConfigCalled++;
-  debugObject.postReloadConfigSuccess = (TS_SUCCESS == reloadStatus);
+  debugObject.postReloadConfigStatus = reloadStatus;
 }
 
 /* The folowing functions are meant for unit testing */
diff --git a/proxy/http/remap/unit-tests/plugin_testing_common.h b/proxy/http/remap/unit-tests/plugin_testing_common.h
index 3662d0c..f96c420 100644
--- a/proxy/http/remap/unit-tests/plugin_testing_common.h
+++ b/proxy/http/remap/unit-tests/plugin_testing_common.h
@@ -51,19 +51,19 @@
   void
   clear()
   {
-    contextInit             = nullptr;
-    contextInitInstance     = nullptr;
-    doRemapCalled           = 0;
-    initCalled              = 0;
-    doneCalled              = 0;
-    initInstanceCalled      = 0;
-    deleteInstanceCalled    = 0;
-    preReloadConfigCalled   = 0;
-    postReloadConfigCalled  = 0;
-    postReloadConfigSuccess = 0;
-    ih                      = nullptr;
-    argc                    = 0;
-    argv                    = nullptr;
+    contextInit            = nullptr;
+    contextInitInstance    = nullptr;
+    doRemapCalled          = 0;
+    initCalled             = 0;
+    doneCalled             = 0;
+    initInstanceCalled     = 0;
+    deleteInstanceCalled   = 0;
+    preReloadConfigCalled  = 0;
+    postReloadConfigCalled = 0;
+    postReloadConfigStatus = TSREMAP_CONFIG_RELOAD_FAILURE;
+    ih                     = nullptr;
+    argc                   = 0;
+    argv                   = nullptr;
   }
 
   /* Input fields used to set the test behavior of the plugin call-backs */
@@ -71,19 +71,19 @@
   void *input_ih;    /* the value to be returned by the plugin instance init function */
 
   /* Output fields showing what happend during the test */
-  const PluginThreadContext *contextInit         = nullptr; /* plugin initialization context */
-  const PluginThreadContext *contextInitInstance = nullptr; /* plugin instance initialization context */
-  int doRemapCalled                              = 0;       /* mark if remap was called */
-  int initCalled                                 = 0;       /* mark if plugin init was called */
-  int doneCalled                                 = 0;       /* mark if done was called */
-  int initInstanceCalled                         = 0;       /* mark if instance init was called */
-  int deleteInstanceCalled                       = 0;       /* mark if delete instance was called */
-  int preReloadConfigCalled                      = 0;       /* mark if pre-reload config was called */
-  int postReloadConfigCalled                     = 0;       /* mark if post-reload config was called */
-  bool postReloadConfigSuccess                   = 0;       /* mark if plugin reload status is passed correctly */
-  void *ih                                       = nullptr; /* instance handler */
-  int argc                                       = 0;       /* number of plugin instance parameters received by the plugin */
-  char **argv                                    = nullptr; /* plugin instance parameters received by the plugin */
+  const PluginThreadContext *contextInit         = nullptr;                   /* plugin initialization context */
+  const PluginThreadContext *contextInitInstance = nullptr;                   /* plugin instance initialization context */
+  int doRemapCalled                              = 0;                         /* mark if remap was called */
+  int initCalled                                 = 0;                         /* mark if plugin init was called */
+  int doneCalled                                 = 0;                         /* mark if done was called */
+  int initInstanceCalled                         = 0;                         /* mark if instance init was called */
+  int deleteInstanceCalled                       = 0;                         /* mark if delete instance was called */
+  int preReloadConfigCalled                      = 0;                         /* mark if pre-reload config was called */
+  int postReloadConfigCalled                     = 0;                         /* mark if post-reload config was called */
+  TSRemapReloadStatus postReloadConfigStatus = TSREMAP_CONFIG_RELOAD_FAILURE; /* mark if plugin reload status is passed correctly */
+  void *ih                                   = nullptr;                       /* instance handler */
+  int argc                                   = 0;       /* number of plugin instance parameters received by the plugin */
+  char **argv                                = nullptr; /* plugin instance parameters received by the plugin */
 };
 
 #ifdef __cplusplus
diff --git a/proxy/http/remap/unit-tests/test_PluginDso.cc b/proxy/http/remap/unit-tests/test_PluginDso.cc
index 1635a65..2db5d1c 100644
--- a/proxy/http/remap/unit-tests/test_PluginDso.cc
+++ b/proxy/http/remap/unit-tests/test_PluginDso.cc
@@ -73,7 +73,7 @@
   {
   }
   virtual void
-  indicatePostReload(TSReturnCode reloadStatus)
+  indicatePostReload(TSRemapReloadStatus reloadStatus)
   {
   }
   virtual bool
diff --git a/proxy/http/remap/unit-tests/test_PluginFactory.cc b/proxy/http/remap/unit-tests/test_PluginFactory.cc
index 1c75bbe..1456f20 100644
--- a/proxy/http/remap/unit-tests/test_PluginFactory.cc
+++ b/proxy/http/remap/unit-tests/test_PluginFactory.cc
@@ -556,7 +556,7 @@
   {
     WHEN("(1) signal pre-new-config-load, (2) signal post-new-config-load, (3) old-config deactivate")
     {
-      /* Simulate configuration without plugins - an unused factory */
+      /* Simulate configuration with 1 factory and 1 plugin */
       setupConfigPathTest(configName1, buildPath, uuid_t1, effectivePath1, runtimePath1, 1556825556);
       PluginFactoryUnitTest *factory1 = getFactory(uuid_t1);
       RemapPluginInst *plugin1        = factory1->getRemapPlugin(configName1, 0, nullptr, error);
@@ -581,19 +581,19 @@
 
         /* Assume (re)load was done OK and test */
         debugObject->clear();
-        factory1->indicatePostReload(TS_SUCCESS);
+        factory1->indicatePostReload(/* reload succeeded */ true);
         CHECK(0 == debugObject->deleteInstanceCalled);
         CHECK(0 == debugObject->doneCalled);
         CHECK(1 == debugObject->postReloadConfigCalled);
-        CHECK(true == debugObject->postReloadConfigSuccess);
+        CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject->postReloadConfigStatus);
 
         /* Assume (re)load failed and test */
         debugObject->clear();
-        factory1->indicatePostReload(TS_ERROR);
+        factory1->indicatePostReload(/* reload succeeded */ false);
         CHECK(0 == debugObject->deleteInstanceCalled);
         CHECK(0 == debugObject->doneCalled);
         CHECK(1 == debugObject->postReloadConfigCalled);
-        CHECK(false == debugObject->postReloadConfigSuccess);
+        CHECK(TSREMAP_CONFIG_RELOAD_FAILURE == debugObject->postReloadConfigStatus);
 
         /* ... swap the new and the old config ... */
 
@@ -613,7 +613,7 @@
   {
     WHEN("(1) signal pre-new-config-load, (2) signal post-new-config-load, (3) old-config deactivate")
     {
-      /* Simulate configuration without plugins - an unused factory */
+      /* Simulate configuration with 1 factories and 2 plugin */
       setupConfigPathTest(configName1, buildPath, uuid_t1, effectivePath1, runtimePath1, 1556825556);
       setupConfigPathTest(configName2, buildPath, uuid_t1, effectivePath2, runtimePath2, 1556825556, /* append */ true);
       PluginFactoryUnitTest *factory1 = getFactory(uuid_t1);
@@ -646,28 +646,28 @@
         /* Assume (re)load was done OK */
         debugObject1->clear();
         debugObject2->clear();
-        factory1->indicatePostReload(TS_SUCCESS);
+        factory1->indicatePostReload(/* reload succeeded */ true);
         CHECK(0 == debugObject1->deleteInstanceCalled);
         CHECK(0 == debugObject1->doneCalled);
         CHECK(1 == debugObject1->postReloadConfigCalled);
-        CHECK(true == debugObject1->postReloadConfigSuccess);
+        CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject1->postReloadConfigStatus);
         CHECK(0 == debugObject2->deleteInstanceCalled);
         CHECK(0 == debugObject2->doneCalled);
         CHECK(1 == debugObject2->postReloadConfigCalled);
-        CHECK(true == debugObject2->postReloadConfigSuccess);
+        CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject2->postReloadConfigStatus);
 
         /* Assume (re)load failed */
         debugObject1->clear();
         debugObject2->clear();
-        factory1->indicatePostReload(TS_ERROR);
+        factory1->indicatePostReload(/* reload succeeded */ false);
         CHECK(0 == debugObject1->deleteInstanceCalled);
         CHECK(0 == debugObject1->doneCalled);
         CHECK(1 == debugObject1->postReloadConfigCalled);
-        CHECK(false == debugObject1->postReloadConfigSuccess);
+        CHECK(TSREMAP_CONFIG_RELOAD_FAILURE == debugObject1->postReloadConfigStatus);
         CHECK(0 == debugObject2->deleteInstanceCalled);
         CHECK(0 == debugObject2->doneCalled);
         CHECK(1 == debugObject2->postReloadConfigCalled);
-        CHECK(false == debugObject2->postReloadConfigSuccess);
+        CHECK(TSREMAP_CONFIG_RELOAD_FAILURE == debugObject2->postReloadConfigStatus);
 
         /* ... swap the new and the old config ... */
 
@@ -691,7 +691,7 @@
   {
     WHEN("indicating de-activation of the factories")
     {
-      /* Simulate configuration without plugins - an unused factory */
+      /* Simulate configuration with 2 factories and 1 plugin */
       setupConfigPathTest(configName1, buildPath, uuid_t1, effectivePath1, runtimePath1, 1556825556);
       PluginFactoryUnitTest *factory1 = getFactory(uuid_t1);
       PluginFactoryUnitTest *factory2 = getFactory(uuid_t2);
@@ -724,4 +724,63 @@
       clean();
     }
   }
+
+  GIVEN("configuration with 2 plugin loaded by 2 factories")
+  {
+    WHEN("2 plugins are loaded by the 1st factory and only one of them loaded by the 2nd factory")
+    {
+      /* Simulate configuration with 2 factories and 2 different plugins */
+      setupConfigPathTest(configName1, buildPath, uuid_t1, effectivePath1, runtimePath1, 1556825556, /* append */ false);
+      setupConfigPathTest(configName2, buildPath, uuid_t1, effectivePath2, runtimePath2, 1556825556, /* append */ true);
+      PluginFactoryUnitTest *factory1 = getFactory(uuid_t1);
+      PluginFactoryUnitTest *factory2 = getFactory(uuid_t2);
+
+      /* 2 plugins loaded by the 1st factory */
+      RemapPluginInst *pluginInst1 = factory1->getRemapPlugin(configName1, 0, nullptr, error);
+      RemapPluginInst *pluginInst2 = factory1->getRemapPlugin(configName2, 0, nullptr, error);
+
+      /* only 1 plugin loaded by the 2st factory */
+      RemapPluginInst *pluginInst3 = factory2->getRemapPlugin(configName1, 0, nullptr, error);
+
+      /* pluginInst1 and pluginInst3 should be using the same plugin DSO named configName1
+       * pluginInst2 should be using plugin DSO named configName 2*/
+      CHECK_FALSE(nullptr == pluginInst1);
+      CHECK_FALSE(nullptr == pluginInst2);
+      CHECK_FALSE(nullptr == pluginInst3);
+      CHECK(&pluginInst1->_plugin == &pluginInst3->_plugin);
+
+      /* Get test objects for the 2 plugins used by the 3 instances from the 2 factories */
+      PluginDebugObject *debugObject1 = getDebugObject(pluginInst1->_plugin);
+      PluginDebugObject *debugObject2 = getDebugObject(pluginInst2->_plugin);
+
+      THEN(
+        "expect the plugin that is not loaded by the second factory to receive 'plugin unused' notification from the 2nd factory")
+      {
+        /* Factory 1: reload was OK and both plugins were part of the configuration that used/instantiated that factory */
+        debugObject1->clear();
+        debugObject2->clear();
+
+        factory1->indicatePostReload(/* reload succeeded */ true);
+        CHECK(1 == debugObject1->postReloadConfigCalled);
+        CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject1->postReloadConfigStatus);
+        CHECK(1 == debugObject2->postReloadConfigCalled);
+        CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject2->postReloadConfigStatus);
+
+        /* Factory 2: (re)load was OK and only 1 plugin was part of the configuration that used/instantiated that factory */
+        debugObject1->clear();
+        debugObject2->clear();
+
+        factory2->indicatePostReload(/* reload succeeded */ true);
+        CHECK(1 == debugObject1->postReloadConfigCalled);
+        CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject1->postReloadConfigStatus);
+        CHECK(1 == debugObject2->postReloadConfigCalled);
+        CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED == debugObject2->postReloadConfigStatus);
+
+        delete factory1;
+        delete factory2;
+      }
+
+      clean();
+    }
+  }
 }
diff --git a/proxy/http/remap/unit-tests/test_RemapPlugin.cc b/proxy/http/remap/unit-tests/test_RemapPlugin.cc
index 49be30f..0184ab2 100644
--- a/proxy/http/remap/unit-tests/test_RemapPlugin.cc
+++ b/proxy/http/remap/unit-tests/test_RemapPlugin.cc
@@ -422,17 +422,50 @@
     bool result = loadPlugin(plugin, error, debugObject);
     CHECK(true == result);
 
-    WHEN("'config reload' is called")
+    WHEN("'config reload' failed")
     {
       debugObject->clear();
 
       plugin->indicatePreReload();
-      plugin->indicatePostReload(TS_SUCCESS);
+      plugin->indicatePostReload(TSREMAP_CONFIG_RELOAD_FAILURE);
 
       THEN("expect it to run")
       {
         CHECK(1 == debugObject->preReloadConfigCalled);
         CHECK(1 == debugObject->postReloadConfigCalled);
+        CHECK(TSREMAP_CONFIG_RELOAD_FAILURE == debugObject->postReloadConfigStatus);
+      }
+      cleanupSandBox(plugin);
+    }
+
+    WHEN("'config reload' is successful and the plugin is part of the new configuration")
+    {
+      debugObject->clear();
+
+      plugin->indicatePreReload();
+      plugin->indicatePostReload(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED);
+
+      THEN("expect it to run")
+      {
+        CHECK(1 == debugObject->preReloadConfigCalled);
+        CHECK(1 == debugObject->postReloadConfigCalled);
+        CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED == debugObject->postReloadConfigStatus);
+      }
+      cleanupSandBox(plugin);
+    }
+
+    WHEN("'config reload' is successful and the plugin is part of the new configuration")
+    {
+      debugObject->clear();
+
+      plugin->indicatePreReload();
+      plugin->indicatePostReload(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED);
+
+      THEN("expect it to run")
+      {
+        CHECK(1 == debugObject->preReloadConfigCalled);
+        CHECK(1 == debugObject->postReloadConfigCalled);
+        CHECK(TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED == debugObject->postReloadConfigStatus);
       }
       cleanupSandBox(plugin);
     }