revise handling plugin in Action
authorYoungjae Shin <yj99.shin@samsung.com>
Tue, 21 Apr 2020 01:33:52 +0000 (10:33 +0900)
committerYoungjae Shin <yj99.shin@samsung.com>
Tue, 21 Apr 2020 01:36:00 +0000 (10:36 +0900)
19 files changed:
example/mode/tizen_normalEx2_mode.xml
include/Plugin.h
include/PluginAction.h
plugin/TestPlugin.cpp
plugin/TestPluginAction.cpp
plugin/TestPluginAction.h
plugin/tizen_test_rule.xml
supervisor/Action.cpp
supervisor/Action.h
supervisor/ActionRule.h
supervisor/ModeCareTaker.cpp
supervisor/ModeCareTaker.h
supervisor/ModeManager.cpp
supervisor/PluginMapper.cpp
supervisor/RuleManager.cpp
supervisor/TAction.h
supervisor/TActionRule.h
supervisor/UndoInfoParser.cpp
unittest/modes_test_plugin.cpp

index 22614f1058d959aa0626727e0e69562ac72282e7..227ec5a8bd7c6e4225e631d60bc69239a275806c 100644 (file)
@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <tizenModes xmlns="http://www.tizen.org" version="6.0">
   <mode name="ex2" type="normal" hidden="true">
-    <action ID="1" rule="test.printInt" stopOnErr="true" restrict="lock" priority="-100">PRINT_FOUR</action>
-    <action ID="wifiOff" rule="test.printBool" restrict="lock" priority="-100">off</action>
+    <action ID="1" rule="test.printInt" stopOnErr="true" restrict="lock">PRINT_FOUR</action>
+    <action ID="wifiOff" rule="test.printBool" restrict="lock">off</action>
+    <action rule="test.alwaySameValue">test</action>
   </mode>
 </tizenModes>
index 964ac167851929b3b20391bfd7444b4fafccc385..65378a04376d8982a3eb11b98dafdb83d9497eaa 100644 (file)
@@ -23,12 +23,8 @@ namespace ModeSupervisorNamespace {
 
        class Plugin {
        public:
-               Plugin()
-               {
-               }
-               virtual ~Plugin()
-               {
-               }
+               Plugin() = default;
+               virtual ~Plugin() = default;
 
                void setName(const std::string &pluginName)
                {
@@ -40,48 +36,19 @@ namespace ModeSupervisorNamespace {
                        return name;
                }
 
-               virtual int set(const std::string &key, int val, PluginAction **piAction)
-               {
-                       return MODES_ERROR_NOT_SUPPORTED;
-               }
-               virtual int set(const std::string &key, double val, PluginAction **piAction)
-               {
-                       return MODES_ERROR_NOT_SUPPORTED;
-               }
-               virtual int set(const std::string &key, bool val, PluginAction **piAction)
-               {
-                       return MODES_ERROR_NOT_SUPPORTED;
-               }
-               virtual int set(const std::string &key, const std::string &val, PluginAction **piAction)
-               {
-                       return MODES_ERROR_NOT_SUPPORTED;
-               }
-               virtual void undo(PluginAction *piAction)
-               {
-                       if (piAction) {
-                               piAction->undo();
-                               delete piAction;
-                       }
-               }
-               virtual PluginAction* getUndoAction(const std::string &key, const std::string &info)
-               {
-                       return nullptr;
-               }
-               virtual std::string serializeAction(PluginAction *piAction)
-               {
-                       if (NULL == piAction)
-                               return std::string();
+               //It should returns dynamic allocated instance of PluginAction
+               virtual PluginAction* newAction(const std::string &key) = 0;
 
-                       return piAction->serialize();
-               }
-               void freeAction(PluginAction *piAction)
+               //Using destructor of PluginAction without overriding is recommended
+               virtual void deleteAction(PluginAction *piAction)
                {
+                       //release resources of piAction
                        delete piAction;
                }
        private:
-               std::string name;     /* plugin key */
+               std::string name;
        };
 
-       typedef Plugin *create_t();
-       typedef void destroy_t(Plugin *);
+       typedef Plugin* (*createFunc)(void);
+       typedef void (*destroyFunc)(Plugin*);
 }
index aba03bddb52b4057b7255138a2d30fcb55fa6773..e42c77ea1fda8a0f13186ed1f5538ca1e113c7c9 100644 (file)
@@ -24,36 +24,74 @@ namespace ModeSupervisorNamespace {
 
        class PluginAction {
        public:
-               PluginAction(const std::string &actionName)
-                       : name(actionName)
+               PluginAction(const std::string &actionKey)
+                       : key(actionKey)
                {
                }
                virtual ~PluginAction() = default;
 
-               std::string getName()
+               std::string getKey()
                {
-                       return name;
+                       return key;
                }
+
+               //If it is true, the Action is ignored.
+               //It is possible to get the old value in this procedure
+               //because the set() is immediately called after this function
+               virtual bool IsCurrentValue(int val)
+               {
+                       return false;
+               }
+               virtual bool IsCurrentValue(double val)
+               {
+                       return false;
+               }
+               virtual bool IsCurrentValue(bool val)
+               {
+                       return false;
+               }
+               virtual bool IsCurrentValue(const std::string &val)
+               {
+                       return false;
+               }
+
+               virtual int set(int val)
+               {
+                       return MODES_ERROR_NOT_SUPPORTED;
+               }
+               virtual int set(double val)
+               {
+                       return MODES_ERROR_NOT_SUPPORTED;
+               }
+               virtual int set(bool val)
+               {
+                       return MODES_ERROR_NOT_SUPPORTED;
+               }
+               virtual int set(const std::string &val)
+               {
+                       return MODES_ERROR_NOT_SUPPORTED;
+               }
+
                virtual void undo()
                {
                }
-               virtual std::string serialize()
+               virtual std::string getUndoInfo()
                {
                        return std::string();
                }
-               virtual int parse(const std::string &data)
+               virtual int setUndoInfo(const std::string &info)
                {
                        return MODES_ERROR_NOT_SUPPORTED;
                }
                virtual int setChangedCallback(valueChangedCB callback, void *userData)
                {
+                       // The callback should be called when the value is changed(Not Same).
                        return MODES_ERROR_NOT_SUPPORTED;
                }
                virtual void unSetChangedCallback(valueChangedCB callback, void *userData)
                {
                }
-       private:
-               const std::string name;
+       protected:
+               const std::string key;
        };
-
 }
index fd65120efb15cb3cccec4390d7edacdb775f0f3a..2278527e80c92c8ccd71d6015a3ef76eac8db357 100644 (file)
@@ -13,9 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <thread>
-#include <chrono>
-#include <glib.h>
 #include "modes_errors.h"
 #include "Plugin.h"
 #include "PluginAction.h"
@@ -30,29 +27,15 @@ private:
 
 public:
        TestPlugin();
-       ~TestPlugin();
+       ~TestPlugin() override = default;
 
-       int set(const std::string &key, int val, PluginAction **piAction) override;
-       int set(const std::string &key, double val, PluginAction **piAction) override;
-       int set(const std::string &key, bool val, PluginAction **piAction) override;
-       int set(const std::string &key, const std::string &val, PluginAction **piAction) override;
-       void undo(PluginAction *piAction) override;
-       PluginAction* getUndoAction(const std::string &key, const std::string &info) override;
-private:
-       static gboolean changeTimeout(gpointer data)
-       {
-               RETV_IF(nullptr == data, G_SOURCE_REMOVE);
-
-               TestPluginAction *testAction = (TestPluginAction*)data;
-               testAction->callChangedCB();
-
-               return  G_SOURCE_REMOVE;
-       }
+       PluginAction* newAction(const std::string &key) override;
+       void deleteAction(PluginAction *piAction) override;
 };
 
-extern "C" API Plugin *objectCreate(void)
+extern "C" API PluginobjectCreate(void)
 {
-       return new TestPlugin;
+       return new TestPlugin();
 }
 
 extern "C" API void objectDelete(Plugin *plugin)
@@ -60,105 +43,19 @@ extern "C" API void objectDelete(Plugin *plugin)
        delete plugin;
 }
 
-
 TestPlugin::TestPlugin()
 {
        setName("test");
 }
 
-TestPlugin::~TestPlugin()
-{
-}
-
-int TestPlugin::set(const std::string &key, int val, PluginAction **piAction)
+PluginAction* TestPlugin::newAction(const std::string &key)
 {
-       TestPluginAction *testAction = new TestPluginAction(key);
-
-       if ("changeAccuracy" == key) {
-               DBG("set(%s, %d)", key.c_str(), val);
-       } else if ("exactness" == key) {
-               DBG("set(%s, %d)", key.c_str(), val);
-       } else if ("nightLight" == key) {
-               DBG("set(%s, %d)", key.c_str(), val);
-       } else if ("printInt" == key) {
-               DBG("set(%s, %d)", key.c_str(), val);
-       } else if ("sleep" == key) {
-               std::this_thread::sleep_for(std::chrono::seconds(val));
-               DBG("set(%s, %d)", key.c_str(), val);
-       } else if ("sleepErrorReturn" == key) {
-               std::this_thread::sleep_for(std::chrono::seconds(val));
-               delete testAction;
-               DBG("set(%s, %d)", key.c_str(), val);
-               return MODES_ERROR_SYSTEM;
-       } else if ("changeTime" == key) {
-               if (piAction)
-                       g_timeout_add_seconds(val, changeTimeout, (void*)testAction);
-               DBG("set(%s, %d)", key.c_str(), val);
-       } else {
-               ERR("Unknown key(%s)", key.c_str());
-               delete testAction;
-               return MODES_ERROR_NOT_SUPPORTED;
-       }
-
-       if (piAction)
-               *piAction = testAction;
-       else
-               delete testAction;
-
-       return MODES_ERROR_NONE;
-}
-
-int TestPlugin::set(const std::string &key, double val, PluginAction **piAction)
-{
-       DBG("TestPlugin::set double ( %s, %lf )", key.c_str(), val);
-
-       if (piAction) {
-               TestPluginAction *testAction = new TestPluginAction(key);
-               *piAction = testAction;
-       }
-       return MODES_ERROR_NONE;
+       return new TestPluginAction(key);
 }
 
-int TestPlugin::set(const std::string &key, bool val, PluginAction **piAction)
+void TestPlugin::deleteAction(PluginAction *piAction)
 {
-       DBG("TestPlugin::set bool ( %s, %s )", key.c_str(), val ? "true" : "false");
-
-       if ("printBool" != key) {
-               ERR("Unknown key(%s)", key.c_str());
-               return MODES_ERROR_NOT_SUPPORTED;
-       }
-
-       if (piAction) {
-               TestPluginAction *testAction = new TestPluginAction(key);
-               *piAction = testAction;
-       }
-       return MODES_ERROR_NONE;
-}
-
-int TestPlugin::set(const std::string &key, const std::string &val, PluginAction **piAction)
-{
-       DBG("TestPlugin::set string ( %s, %s )", key.c_str(), val.c_str());
-
-       if (piAction) {
-               TestPluginAction *testAction = new TestPluginAction(key);
-               *piAction = testAction;
-       }
-       return MODES_ERROR_NONE;
-}
-
-void TestPlugin::undo(PluginAction *piAction)
-{
-       if (piAction) {
-               DBG("TestPlugin::undo(Action:%s)", piAction->getName().c_str());
-               delete piAction;
-       }
-}
-
-PluginAction* TestPlugin::getUndoAction(const std::string &key, const std::string &info)
-{
-       // parse the key for making PluginAction
-       TestPluginAction *piAction = new TestPluginAction(key);
-       piAction->parse(info);
-
-       return piAction;
+       //release resource of piAction
+       //Using destructor of PluginAction without overriding is recommended
+       delete piAction;
 }
index 9b86b2e55a7affe191c62ed0b83edd7b2fecc01a..a7296cd81c6df6747fa76708ecdbce6dbcca9417 100644 (file)
  */
 #include "TestPluginAction.h"
 
+#include <thread>
+#include <chrono>
 #include "modes_errors.h"
 #include "common/log.h"
 #include "common/definitions.h"
 
 MODES_NAMESPACE_USE;
 
-TestPluginAction::TestPluginAction(const std::string &name)
-       : PluginAction(name), cb(nullptr), cbData(nullptr)
+TestPluginAction::TestPluginAction(const std::string &actionKey)
+       : PluginAction(actionKey), cb(nullptr), cbData(nullptr)
 {
 }
 
-TestPluginAction::~TestPluginAction()
+bool TestPluginAction::IsCurrentValue(const std::string &val)
 {
+       return true;
+}
+
+int TestPluginAction::set(int val)
+{
+       if ("changeAccuracy" == key) {
+               DBG("set(%s, %d)", key.c_str(), val);
+       } else if ("exactness" == key) {
+               DBG("set(%s, %d)", key.c_str(), val);
+       } else if ("nightLight" == key) {
+               DBG("set(%s, %d)", key.c_str(), val);
+       } else if ("printInt" == key) {
+               DBG("set(%s, %d)", key.c_str(), val);
+       } else if ("sleep" == key) {
+               std::this_thread::sleep_for(std::chrono::seconds(val));
+               DBG("set(%s, %d)", key.c_str(), val);
+       } else if ("sleepErrorReturn" == key) {
+               std::this_thread::sleep_for(std::chrono::seconds(val));
+               DBG("set(%s, %d)", key.c_str(), val);
+               return MODES_ERROR_SYSTEM;
+       } else if ("changeTime" == key) {
+               g_timeout_add_seconds(val, changeTimeout, this);
+               DBG("set(%s, %d)", key.c_str(), val);
+       } else {
+               ERR("Unknown key(%s)", key.c_str());
+               return MODES_ERROR_NOT_SUPPORTED;
+       }
+
+       return MODES_ERROR_NONE;
+}
+
+int TestPluginAction::set(double val)
+{
+       DBG("TestPlugin::set double (%s, %lf)", key.c_str(), val);
+
+       if ("printFloat" != key) {
+               ERR("Unknown key(%s)", key.c_str());
+               return MODES_ERROR_NOT_SUPPORTED;
+       }
+       return MODES_ERROR_NONE;
+}
+
+int TestPluginAction::set(bool val)
+{
+       DBG("TestPlugin::set bool (%s, %s)", key.c_str(), val ? "true" : "false");
+
+       if ("printBool" != key) {
+               ERR("Unknown key(%s)", key.c_str());
+               return MODES_ERROR_NOT_SUPPORTED;
+       }
+
+       return MODES_ERROR_NONE;
+}
+
+int TestPluginAction::set(const std::string &val)
+{
+       DBG("TestPlugin::set string (%s, %s)", key.c_str(), val.c_str());
+
+       if ("alwaySameValue" == key) {
+               ERR("key(%s) should not reach here", key.c_str());
+               return MODES_ERROR_NOT_SUPPORTED;
+       }
+
+       return MODES_ERROR_NONE;
 }
 
 void TestPluginAction::undo()
 {
-       INFO("TestPluginAction::undo(%s) is Called", getName().c_str());
+       INFO("TestPluginAction::undo(%s) is Called", getKey().c_str());
 }
 
-std::string TestPluginAction::serialize()
+std::string TestPluginAction::getUndoInfo()
 {
-       return getName();
+       return getKey();
 }
 
-int TestPluginAction::parse(const std::string &info)
+int TestPluginAction::setUndoInfo(const std::string &info)
 {
-       DBG("serialized info(%s)", info.c_str());
+       INFO("Undo info(%s)", info.c_str());
        return MODES_ERROR_NONE;
 }
 
@@ -62,8 +128,18 @@ void TestPluginAction::unSetChangedCallback(valueChangedCB callback, void *userD
 
 void TestPluginAction::callChangedCB()
 {
-       INFO("%s is changed", getName().c_str());
+       INFO("%s is changed", getKey().c_str());
 
        if (cb)
                cb(cbData);
 }
+
+gboolean TestPluginAction::changeTimeout(gpointer data)
+{
+       RETV_IF(nullptr == data, G_SOURCE_REMOVE);
+
+       TestPluginAction *testAction = (TestPluginAction*)data;
+       testAction->callChangedCB();
+
+       return  G_SOURCE_REMOVE;
+}
index 2a35c3979e5ce86bf629b52893c1d92ee0e7435b..c62cafbec40c7651b065f4d837b88ececd1c7ff6 100644 (file)
@@ -15,6 +15,7 @@
  */
 #pragma once
 
+#include <glib.h>
 #include <string>
 #include "PluginAction.h"
 #include "common/definitions.h"
@@ -23,16 +24,24 @@ MODES_NAMESPACE_BEGIN
 
 class TestPluginAction : public PluginAction {
 public:
-       TestPluginAction(const std::string &name);
-       ~TestPluginAction() override;
+       TestPluginAction(const std::string &actionKey);
+       ~TestPluginAction() override = default;
 
+       bool IsCurrentValue(const std::string &val) override;
+
+       int set(int val) override;
+       int set(double val) override;
+       int set(bool val) override;
+       int set(const std::string &val) override;
        void undo() override;
-       std::string serialize() override;
-       int parse(const std::string &data) override;
+       std::string getUndoInfo() override;
+       int setUndoInfo(const std::string &data) override;
        int setChangedCallback(valueChangedCB callback, void *userData) override;
        void unSetChangedCallback(valueChangedCB callback, void *userData) override;
        void callChangedCB();
 private:
+       static gboolean changeTimeout(gpointer data);
+
        valueChangedCB cb;
        void *cbData;
 };
index 838e9913540e0a46a60d0d4c4e337d35b1ba6334..d27fa64bdad9f9abd3fc7b70a79b1a38764081da 100644 (file)
@@ -49,7 +49,7 @@
       <desc>It prints boolean value</desc>
       <domain>System</domain>
     </rule>
-    <rule name="test.printDouble" type="float" since="6.0" plugin="test">
+    <rule name="test.printFloat" type="float" since="6.0" plugin="test">
       <privilege>http://tizen.org/privilege/systemsettings.admin</privilege>
       <desc>It prints double value</desc>
       <domain>System</domain>
@@ -72,5 +72,9 @@
       <desc>Call Change callback after value seconds</desc>
       <domain>System</domain>
     </rule>
+    <rule name="test.alwaySameValue" type="string" since="6.0">
+      <desc>IsCurrentValue() Always returns true</desc>
+      <domain>System</domain>
+    </rule>
   </actionRule>
 </tizenModes>
index fc85b5a9f52046b5dc194bb982521d2529e7afa7..d0192ba13bbaad09cf17e04db56604a0cf54fd9a 100644 (file)
  */
 #include "Action.h"
 
+#include <memory>
 #include "mdss.h"
 #include "ModesEx.h"
 
 MODES_NAMESPACE_USE;
 
-Action::Action()
-       : isChanged(false), type(SYNC), life(PERMANENT), plugin(nullptr), piAction(nullptr), stopOnErr(false), restriction(NONE), locked(false)
+std::map<std::string, Action*> Action::subscribedActions;
 
-{
-}
-
-Action::Action(const std::string &name)
-       : ruleName(name), isChanged(false), type(SYNC), life(PERMANENT), plugin(nullptr), piAction(nullptr), stopOnErr(false), restriction(NONE), locked(false)
+Action::Action(const std::string &name, std::shared_ptr<PluginAction> pluginAction)
+       : ruleName(name), ignoreUndo(false), type(SYNC), life(PERMANENT), piAction(pluginAction),
+       locked(false), stopOnErr(false), subscribed(false), restriction(NONE)
 {
 }
 
 Action::~Action()
 {
-       if (plugin)
-               plugin->freeAction(piAction);
 }
 
 void Action::printInfo()
 {
-       DBG("Action(%s):ID(%s), Restrict(%d) piAction(%p)", getRuleName().c_str(), getID().c_str(), getRestrict(), piAction);
+       DBG("Action(%s):ID(%s), Restrict(%d)", getRuleName().c_str(), getID().c_str(), getRestrict());
 }
 
 void Action::setRuleName(const std::string &data)
@@ -112,11 +108,6 @@ bool Action::isLocked()
        return locked;
 }
 
-void Action::setPlugin(Plugin *pi)
-{
-       plugin = pi;
-}
-
 void Action::setPrivilege(const std::string &val)
 {
        privilege = val;
@@ -137,23 +128,69 @@ void Action::detachObserver(ActionObserver *obs)
        observers.remove(obs);
 }
 
-void Action::notifyObservers()
+std::string Action::backupUndoInfo()
 {
-       RET_IF(true == isChanged);
+       return piAction->getUndoInfo();
+}
+
+int Action::restoreUndoInfo(const std::string &info)
+{
+       int ret = piAction->setUndoInfo(info);
+       if (MODES_ERROR_NONE != ret) {
+               ignoreUndo = true;
+               ERR("piAction(%s) setUndoInfo(%s) Fail", piAction->getKey().c_str(), info.c_str());
+               return ret;
+       }
+       subscribeChanges();
+
+       return MODES_ERROR_NONE;
+}
+
+void Action::subscribeChanges()
+{
+       int ret = piAction->setChangedCallback(valueChangedCallback, this);
+       if (MODES_ERROR_NONE != ret) {
+               WARN("piAction(%s) setChangedCallback() Fail(%d)", piAction->getKey().c_str(), ret);
+       } else {
+               auto result = subscribedActions.insert(std::pair<std::string, Action*>(ruleName, this));
+               if (false == result.second)
+                       WARN("Action(%s), already exists", ruleName.c_str());
+               subscribed = true;
+       }
+}
 
+void Action::unsubscribeChanges()
+{
+       if (!subscribed)
+               return;
+
+       subscribed = false;
        piAction->unSetChangedCallback(valueChangedCallback, this);
-       isChanged = true;
+       subscribedActions.erase(ruleName);
+}
 
-       for (auto it = observers.begin(); it != observers.end(); ++it)
-               (*it)->update(reinterpret_cast<int*>(this));
+void Action::invokeChangedCB()
+{
+       valueChangedCallback(subscribedActions[ruleName]);
 }
 
 void Action::valueChangedCallback(void *userData)
 {
        Action *action = (Action*)userData;
-       RET_IF(NULL == action);
+       RET_IF(nullptr == action);
 
        action->notifyObservers();
 
        DBG("Action(%s) Changed", action->ruleName.c_str());
 }
+
+void Action::notifyObservers()
+{
+       RET_IF(true == ignoreUndo);
+
+       unsubscribeChanges();
+       ignoreUndo = true;
+
+       for (auto it = observers.begin(); it != observers.end(); ++it)
+               (*it)->update(reinterpret_cast<int*>(this));
+}
index fd79812b94dc70f164f57f65f20241bfcf92f1d0..c6369148395a05c632341dfbe392c68995689879 100644 (file)
  */
 #pragma once
 
+#include <map>
 #include <list>
 #include <string>
+#include <memory>
 #include "mdss.h"
-#include "Plugin.h"
 #include "PluginAction.h"
 #include "ActionObserver.h"
 
@@ -42,8 +43,7 @@ public:
                VOLATILE
        } ActionRuleLife;
 
-       Action();
-       Action(const std::string &ruleName);
+       Action(const std::string &ruleName, std::shared_ptr<PluginAction> pluginAction);
        virtual ~Action();
 
        void printInfo();
@@ -61,34 +61,37 @@ public:
        ActionType getType();
        void setLife(ActionRuleLife val);
        ActionRuleLife getLife();
-       void setPlugin(Plugin *pi);
        void setPrivilege(const std::string &val);
        std::string getPrivilege();
        void attachObserver(ActionObserver *obs);
        void detachObserver(ActionObserver *obs);
+       std::string backupUndoInfo();
+       int restoreUndoInfo(const std::string &info);
        virtual int setValue(const std::string &val) = 0;
        virtual std::string getStringOfValue() = 0;
        virtual int apply() = 0;
        virtual int applyOneShot() = 0;
        virtual void undo() = 0;
-       virtual int restoreUndoInfo(const std::string &info) = 0;
-       virtual std::string backupUndoInfo() = 0;
 protected:
-       static void valueChangedCallback(void *userData);
+       void subscribeChanges();
+       void unsubscribeChanges();
+       void invokeChangedCB();
        std::string ruleName;
-       bool isChanged;
+       bool ignoreUndo;
        ActionType type;
        ActionRuleLife life;
-       Plugin *plugin;
-       PluginAction *piAction;
+       std::shared_ptr<PluginAction> piAction;
 private:
+       static void valueChangedCallback(void *userData);
        void notifyObservers();
        std::string id;
        std::string privilege;
+       bool locked; //Another action(same rule) is restricted(LOCK), It is assigned by ConflictManager
        bool stopOnErr;
+       bool subscribed;
        ActionRestrict restriction;
-       bool locked; //Another action(same rule) is restricted(LOCK), It is assigned by ConflictManager
        std::list<ActionObserver*> observers;
+       static std::map<std::string, Action*> subscribedActions;
 };
 
 MODES_NAMESPACE_END
index 17528a74d66919a8735e2c7b2d1ca003cd557eab..824987c2dfa6908b6f00cbd187617cb1e2d91dc1 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <string>
 #include "mdss.h"
+#include "Plugin.h"
 #include "Action.h"
 
 MODES_NAMESPACE_BEGIN
index b5abe515710abfa16705ccd1f98074864e51835b..53989bba0adc4a353d51e0708adc78d06bbb2ba4 100644 (file)
@@ -31,17 +31,17 @@ std::string ModeCareTaker::getUndoInfoDir()
        return undoDir;
 }
 
-void ModeCareTaker::restoreMode(const Mode &mode)
+void ModeCareTaker::realPushMode(const Mode &mode)
 {
        savedModes.insert(std::pair<std::string, Mode>(mode.getName(), mode));
+
+       if (mode.hasEssential())
+               handleEssentialAction(mode);
 }
 
 void ModeCareTaker::pushMode(const Mode &mode)
 {
-       savedModes.insert(std::pair<std::string, Mode>(mode.getName(), mode));
-
-       if (mode.hasEssential())
-               handleEssentialAction(mode);
+       realPushMode(mode);
 
        XMLGenerator gen;
        gen.makeUndoInfoXML(undoDir + "/tizen_" + mode.getName() + MODES_UNDO_FILE_SUFFIX, mode);
index 8b0a0d18c098f553bcb1c1162e97f38ad36c47ab..1efa77634713d89fd3d4bc4bfd4b1e345faceb3a 100644 (file)
@@ -29,7 +29,7 @@ public:
        ~ModeCareTaker() = default;
 
        std::string getUndoInfoDir();
-       void restoreMode(const Mode &mode);
+       void realPushMode(const Mode &mode);
        void pushMode(const Mode &mode);
        int popMode(const std::string &name, Mode &mode);
        bool isConflict(const Mode &mode);
index 5619e338b8ce9aae3555f4ebf6a755dae15aba35..d9f8d2f904837817440e3e37cdf79b10dc2f0ddb 100644 (file)
@@ -291,7 +291,7 @@ bool ModeManager::restoreUndoInfo(const string &dirPath)
                        Mode mode = parser->getMode();
                        undoInfoParser.putUndoInfo(mode);
 
-                       careTaker.restoreMode(mode);
+                       careTaker.realPushMode(mode);
                } catch (std::exception &e) {
                        ERR("parser(%s) Fail(%s)", fileFullPath.c_str(), e.what());
                        if (0 != remove(fileFullPath.c_str()))
index 8c3890331e548f8c984336ef1093237c4666c0a5..0e4001bb8338d32f9e1e89c4a9ea0141964f05e4 100644 (file)
@@ -35,7 +35,7 @@ PluginMapper::PluginMapper(const std::string &dirPath)
 int PluginMapper::loadPlugins()
 {
        DIR *dir;
-       if ((dir = opendir(pluginDir.c_str())) == NULL) {
+       if ((dir = opendir(pluginDir.c_str())) == nullptr) {
                ERR("opendir(%s) Fail(%d)", pluginDir.c_str(), errno);
                throw ModesEx(ModesEx::SYSTEM_ERROR);
        }
@@ -43,7 +43,8 @@ int PluginMapper::loadPlugins()
        struct dirent *entry;
        while ((entry = readdir(dir)) != NULL) {
                std::string file(entry->d_name);
-               if (std::string::npos == file.find(MODES_PLUGIN_LIB_PREFIX)) //library validation
+               //library name validation check
+               if (std::string::npos == file.find(MODES_PLUGIN_LIB_PREFIX))
                        continue;
 
                std::string fileFullPath = pluginDir + "/" + file;
@@ -75,16 +76,16 @@ PluginMapper::PluginPair PluginMapper::loadClass(const std::string &pluginFile)
        }
 
        /* load the symbols */
-       create_t *create_object_func = (create_t *) dlsym(handle, "objectCreate");
-       if (NULL == create_object_func) {
+       createFunc newPlugin = (createFunc)dlsym(handle, "objectCreate");
+       if (nullptr == newPlugin) {
                ERR("dlsym(objectCreate) Fail(Plugin[%s] error[%s])", pluginFile.c_str(), dlerror());
                dlclose(handle);
                throw ModesEx(ModesEx::SYSTEM_ERROR);
        }
 
        /* create an instance of the class */
-       Plugin *object = create_object_func();
-       if (NULL == object) {
+       Plugin *object = newPlugin();
+       if (nullptr == object) {
                ERR("create_object_func(%s) Fail", pluginFile.c_str());
                dlclose(handle);
                throw ModesEx(ModesEx::SYSTEM_ERROR);
@@ -96,19 +97,19 @@ PluginMapper::PluginPair PluginMapper::loadClass(const std::string &pluginFile)
 int PluginMapper::unloadClass(const PluginPair &pluginPair)
 {
        void *handle = pluginPair.first;
-       Plugin *object = pluginPair.second;
-       std::string pluginName = object->getName();
+       Plugin *plugin = pluginPair.second;
+       std::string pluginName = plugin->getName();
 
-       RETVM_IF(NULL == handle, MODES_ERROR_SYSTEM, "handle(%s) is null", pluginName.c_str());
+       RETVM_IF(nullptr == handle, MODES_ERROR_SYSTEM, "No handle(%s)", pluginName.c_str());
 
-       destroy_t *delete_object_func = (destroy_t *)dlsym(handle, "objectDelete");
-       if (NULL == delete_object_func) {
+       destroyFunc deletePlugin = (destroyFunc)dlsym(handle, "objectDelete");
+       if (nullptr == deletePlugin) {
                ERR("dlsym(objectDelete) Fail(plugin[%s] error[%s])", pluginName.c_str(), dlerror());
                dlclose(handle);
                return MODES_ERROR_SYSTEM;
        }
 
-       delete_object_func(object);
+       deletePlugin(plugin);
        dlclose(handle);
 
        return MODES_ERROR_NONE;
index 45ccfd084ce1d1c7fbdf86654f8eff42b58eaa8f..32bd5a0ce0481a0e20b2a2deb009f5b7e64ee44b 100644 (file)
@@ -36,7 +36,7 @@ const xmlChar* const RuleManager::RULE_TAGS[] = {
        (xmlChar*)"privilege",
 };
 
-RuleManager::RuleManager(const std::string & actionRuleDir, const std::string &actionRuleXsd, const std::string &pluginDir)
+RuleManager::RuleManager(const std::string &actionRuleDir, const std::string &actionRuleXsd, const std::string &pluginDir)
        : ruleDir(actionRuleDir), ruleXsd(actionRuleXsd), piMapper(pluginDir)
 {
 }
index 85e54c5c9b2f0869e8ef111dd7a38bd32aaf2fcd..31e80f2410542d2e5715e82a82734a170a5bd3f0 100644 (file)
 #pragma once
 
 #include <map>
+#include <mutex>
 #include <string>
 #include <sstream>
 #include <thread>
 #include "mdss.h"
 #include "Action.h"
+#include "ModesEx.h"
 #include "ValueChecker.h"
 
 MODES_NAMESPACE_BEGIN
@@ -28,18 +30,16 @@ MODES_NAMESPACE_BEGIN
 template <typename T>
 class TAction : public Action {
 public:
-       TAction(const std::string &name)
-               : Action(name), undoing(false)
+       TAction(const std::string &name, std::shared_ptr<PluginAction> pluginAction)
+               : Action(name, pluginAction), undoing(false)
        {
+               if (nullptr == pluginAction)
+                       throw ModesEx(ModesEx::INVALID_ARG);
        }
 
        ~TAction()
        {
-               if (undoing)
-                       undo();
-
-               if (piAction)
-                       piAction->unSetChangedCallback(valueChangedCallback, this);
+               unsubscribeChanges();
        }
 
        void setValueAliases(const std::map<std::string, T> &list)
@@ -80,85 +80,49 @@ public:
                return MODES_ERROR_NONE;
        }
 
-       int restoreUndoInfo(const std::string &info) override
-       {
-               RETVM_IF(NULL == plugin, MODES_ERROR_NO_DATA, "Action(%s) : No plugin", ruleName.c_str());
-
-               int pos = ruleName.find_first_of(".");
-               piAction = plugin->getUndoAction(ruleName.substr(pos + 1), info);
-               if (nullptr == piAction) {
-                       ERR("plugin(%s) getUndoAction() Fail", plugin->getName().c_str());
-                       return MODES_ERROR_NOT_SUPPORTED;
-               }
-               piAction->setChangedCallback(valueChangedCallback, this);
-
-               return MODES_ERROR_NONE;
-       }
-
-       std::string backupUndoInfo() override
-       {
-               RETVM_IF(NULL == plugin, std::string(), "Action(%s) : No plugin", ruleName.c_str());
-
-               if (nullptr == piAction) {
-                       DBG("No plugin Action(%s) for undo", ruleName.c_str());
-                       return std::string();
-               }
-
-               return plugin->serializeAction(piAction);
-       }
-
        int apply() override
        {
-               RETVM_IF(NULL == plugin, MODES_ERROR_NO_DATA, "Action(%s) : No plugin", ruleName.c_str());
+               std::lock_guard<std::mutex> lock(actionMutex);
 
-               int pos = ruleName.find_first_of(".");
-               PluginAction *tmpAction = nullptr;
-               int ret = plugin->set(ruleName.substr(pos + 1), value, &tmpAction);
+               int ret = applySub();
                if (MODES_ERROR_NONE != ret) {
-                       ERR("plugin(%s) set() Fail(%d)", plugin->getName().c_str(), ret);
+                       ignoreUndo = true;
+                       if (MODES_ERROR_ALREADY == ret)
+                               return MODES_ERROR_NONE;
+                       ERR("applySub(%s) Fail(%d)", ruleName.c_str(), ret);
                        return ret;
                }
-               if (tmpAction)
-                       tmpAction->setChangedCallback(valueChangedCallback, this);
 
-               piAction = tmpAction;
+               subscribeChanges();
                return MODES_ERROR_NONE;
        }
 
        int applyOneShot() override
        {
-               RETVM_IF(NULL == plugin, MODES_ERROR_NO_DATA, "Action(%s) : No plugin", ruleName.c_str());
+               std::lock_guard<std::mutex> lock(actionMutex);
 
-               int pos = ruleName.find_first_of(".");
-               PluginAction *tmpAction = nullptr;
-               int ret = plugin->set(ruleName.substr(pos + 1), value, &tmpAction);
+               int ret = applySub();
                if (MODES_ERROR_NONE != ret) {
-                       ERR("plugin(%s) set() Fail(%d)", plugin->getName().c_str(), ret);
-                       return ret;
+                       ignoreUndo = true;
+                       if (MODES_ERROR_ALREADY != ret) {
+                               ERR("applySub(%s) Fail(%d)", ruleName.c_str(), ret);
+                               return ret;
+                       }
                }
 
-               piAction = tmpAction;
                return MODES_ERROR_NONE;
        }
 
        void undo() override
        {
-               RETM_IF(NULL == plugin, "Action(%s) : No plugin", ruleName.c_str());
-
-               //It control multithread condition
-               if (Action::ActionType::ASYNC == type)
-                       undoing = true;
+               std::lock_guard<std::mutex> lock(actionMutex);
 
-               RETM_IF(NULL == piAction, "Plugin(%s) : No piAction(%s)", plugin->getName().c_str(), ruleName.c_str());
-
-               if (isChanged) {
+               if (ignoreUndo) {
                        INFO("Action(%s) : value changed", ruleName.c_str());
-                       plugin->freeAction(piAction);
                } else {
-                       piAction->unSetChangedCallback(valueChangedCallback, this);
-                       plugin->undo(piAction); // piAction is deleted in undo()
+                       unsubscribeChanges();
+                       piAction->undo();
                }
-               piAction = nullptr;
        }
 
 private:
@@ -176,7 +140,26 @@ private:
                }
        };
 
+       int applySub()
+       {
+               if (piAction->IsCurrentValue(value)) {
+                       INFO("Action(%s) is Ignored because it is equal to current value", ruleName.c_str());
+                       return MODES_ERROR_ALREADY;
+               }
+
+               invokeChangedCB();
+
+               int ret = piAction->set(value);
+               if (MODES_ERROR_NONE != ret) {
+                       ERR("piAction(%s) set() Fail(%d)", piAction->getKey().c_str(), ret);
+                       return ret;
+               }
+
+               return MODES_ERROR_NONE;
+       }
+
        std::map<std::string, T, CaseIndependentLess> valueAliases;
+       std::mutex actionMutex;
        bool undoing;
        T value{};
 };
index 8be927f0cbd7680f7a805bcce73b3990d6e6f25a..303c94eb71540e03293a49f8cfb0480383d657d5 100644 (file)
@@ -19,6 +19,7 @@
 #include <list>
 #include <string>
 #include <sstream>
+#include <functional>
 #include "mdss.h"
 #include "TAction.h"
 #include "ActionRule.h"
@@ -35,13 +36,23 @@ public:
 
        Action* makeAction() override
        {
-               TAction<T> *action = new TAction<T>(ruleName);
-               action->setValueAliases(valueAliasList);
-               action->setPrivilege(privilege);
-               action->setPlugin(plugin);
-               action->setLife(life);
+               int pos = ruleName.find_first_of(".");
+               std::string actionKey = ruleName.substr(pos + 1);
+               std::shared_ptr<PluginAction> piAction(plugin->newAction(actionKey),
+                       std::bind(&Plugin::deleteAction, plugin, std::placeholders::_1));
 
-               return action;
+               try {
+                       TAction<T> *action = new TAction<T>(ruleName, piAction);
+                       action->setValueAliases(valueAliasList);
+                       action->setPrivilege(privilege);
+                       action->setLife(life);
+
+                       return action;
+               } catch (ModesEx &e) {
+                       ERR("makeAction() Fail(%s)", e.what());
+               }
+
+               return nullptr;
        }
 
        int addAlias(const std::string &alias, const std::string &value) override
index 286ab34bc259bed1eb795f70ef259eb2935a620c..1a0667116a2a2f4688728cb419c116340dde9a3e 100644 (file)
@@ -70,31 +70,31 @@ void UndoInfoParser::iterateElement(xmlNodePtr node, const std::list<std::shared
 void UndoInfoParser::parseInfo(xmlNodePtr node, const std::list<std::shared_ptr<Action>> &actionList)
 {
        char *ruleName = (char*)xmlGetProp(node, ModesXMLTag::RULE);
-       if (ruleName == NULL) {
-               ERR("rule attribute is null! [%s]", ModesXMLTag::RULE);
-               throw ModesEx(ModesEx::PARSER_ERROR, "rule attribute is null!");
+       if (nullptr == ruleName) {
+               ERR("No value of (%s)", ModesXMLTag::RULE);
+               throw ModesEx(ModesEx::PARSER_ERROR, "No Rule Name");
        }
 
-       auto it = std::find_if_not(actionList.begin(), actionList.end(),
-               [ruleName](std::shared_ptr<Action> a)->bool {return a->getRuleName().compare(ruleName);});
+       auto it = std::find_if(actionList.begin(), actionList.end(),
+               [&ruleName](std::shared_ptr<Action> a) {return (a->getRuleName() == ruleName);});
+
        std::shared_ptr<Action> action = *it;
-       if (action == nullptr) {
+       if (nullptr == action) {
                ERR("Find Action(%s) Fail", ruleName);
                xmlFree(ruleName);
-               throw ModesEx(ModesEx::PARSER_ERROR, "Action is null!");
+               throw ModesEx(ModesEx::PARSER_ERROR, "No Action");
        }
-       xmlFree(ruleName);
 
        char *nodeContent = (char*)xmlNodeGetContent(node);
-       if (nodeContent == NULL)
-               ERR("Node Content is null!");
+       if (nullptr == nodeContent)
+               ERR("No undo Info for Action(%s)", ruleName);
 
        int ret = action->restoreUndoInfo(nodeContent ? nodeContent : "");
+       xmlFree(ruleName);
        xmlFree(nodeContent);
-
        if (MODES_ERROR_NONE != ret) {
                ERR("Action(%s) setValue() Fail(%d)", action->getRuleName().c_str(), ret);
-               throw ModesEx(ModesEx::PARSER_ERROR, "Invalid Action Value");
+               throw ModesEx(ModesEx::PARSER_ERROR, "Invalid UndoInfo");
        }
 
        action->printInfo();
index ea7217df76b7ac88f2c529065507580301f860ab..fe146b7ac48c45621d150d7caccff9c9cdcdafc6 100644 (file)
@@ -83,25 +83,40 @@ TEST(PluginMapper, getPluginTest)
        EXPECT_FALSE(broker.emptyPluginMap());
 
        Plugin *plugin = broker.piMapper.getPlugin("test");
-       ASSERT_TRUE(plugin != NULL);
+       ASSERT_TRUE(plugin);
 
-       ret = plugin->set("printInt", 0, nullptr);
+       PluginAction *piAction = plugin->newAction("printInt");
+       ret = piAction->set(0);
        EXPECT_EQ(ret, MODES_ERROR_NONE);
 
-       ret = plugin->set("printInt", false, nullptr);
+       ret = piAction->set(false);
        EXPECT_EQ(ret, MODES_ERROR_NOT_SUPPORTED);
+       plugin->deleteAction(piAction);
 
-       ret = plugin->set("printDouble", 1.234, nullptr);
+       piAction = plugin->newAction("printFloat");
+       ret = piAction->set(1.234);
        EXPECT_EQ(ret, MODES_ERROR_NONE);
+       plugin->deleteAction(piAction);
 
-       ret = plugin->set("printBool", false, nullptr);
+       piAction = plugin->newAction("printBool");
+       ret = piAction->set(false);
        EXPECT_EQ(ret, MODES_ERROR_NONE);
 
-       ret = plugin->set("printBool", 3, nullptr);
+       ret = piAction->set(3);
        EXPECT_EQ(ret, MODES_ERROR_NOT_SUPPORTED);
+       plugin->deleteAction(piAction);
 
-       ret = plugin->set("printString", string("String value"), nullptr);
+       piAction = plugin->newAction("printString");
+       ret = piAction->set(string("String value"));
        EXPECT_EQ(ret, MODES_ERROR_NONE);
+       plugin->deleteAction(piAction);
+
+       piAction = plugin->newAction("alwaySameValue");
+       bool same = piAction->IsCurrentValue(string("String value"));
+       EXPECT_EQ(same, true);
+       ret = piAction->set(string("String value"));
+       EXPECT_EQ(ret, MODES_ERROR_NOT_SUPPORTED);
+       plugin->deleteAction(piAction);
 
        ret = broker.piMapper.unloadPlugins();
        EXPECT_EQ(ret, MODES_ERROR_NONE);