Flush app registry before releasing file lock
[platform/framework/native/appfw.git] / src / app / FApp_AppRegistryImpl.cpp
index 96db27e..f3d39ed 100644 (file)
  * @brief      This is the implementation for the _AppRegistryImpl class.
  */
 
-#include <FAppAppRegistry.h>
+#include <FBaseSysLog.h>
+#include <FBaseRtMutexGuard.h>
+#include <FIoFile.h>
 #include <FIoRegistry.h>
+#include <FAppAppRegistry.h>
 
-#include <FBaseSysLog.h>
 #include "FApp_AppRegistryImpl.h"
 #include "FApp_AppInfo.h"
 
 using namespace Tizen::Io;
 using namespace Tizen::Base;
+using namespace Tizen::Base::Runtime;
 
 namespace Tizen { namespace App
 {
 
+static const ReadOnlyTag ReadOnly = {};
+static const ReadWriteTag ReadWrite = {};
 
 _AppRegistryImpl::_AppRegistryImpl(void)
-       : __pRegistry(null)
-       , __sectionName(L"__ApplicationStates")
+       : __sectionName(L"__ApplicationStates")
 {
 }
 
-
 _AppRegistryImpl::~_AppRegistryImpl(void)
 {
-       delete __pRegistry;
 }
 
-
 result
 _AppRegistryImpl::Construct(void)
 {
-       result r = E_SUCCESS;
-
-       SysAssertf(__pRegistry == null,
-                       "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class.");
-
        const String& packageId = _AppInfo::GetPackageId();
-       String regName = _AppInfo::GetAppRootPath() + L"data/";
-
        SysAssertf(!packageId.IsEmpty(), "Empty package.");
-       r = regName.Append(packageId);
-       SysTryReturn(NID_APP, !IsFailed(r), r, r, "[%s] String appending has failed.", GetErrorMessage(r));
 
-       __pRegistry = new (std::nothrow) Registry();
-       SysTryCatch(NID_APP, __pRegistry != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
-                          "[E_OUT_OF_MEMORY] Failed while instantiating registry.");
+       __regPath = _AppInfo::GetAppRootPath() + L"data/";
+       result r = __regPath.Append(packageId);
+       SysTryReturnResult(NID_APP, !IsFailed(r), r, "String appending has failed.");
 
-       r = __pRegistry->Construct(regName, true);
-       SysTryCatch(NID_APP, !IsFailed(r), , r, "[%ls] Constructing the registry %s has failed.", regName.GetPointer(),
-                          GetErrorMessage(r));
+       r = __mutex.Create();
+       SysTryReturnResult(NID_APP, !IsFailed(r), r, "Mutex intialization failed.");
 
-       r = __pRegistry->AddSection(__sectionName);
-       if (r == E_SECTION_ALREADY_EXIST)
        {
-               // section may exist already
-               r = E_SUCCESS;
-       }
+               MutexGuard lock(__mutex);
 
-       SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Adding section to registry has failed.", GetErrorMessage(r));
+               Registry reg;
+               r = reg.Construct(__regPath, "a+");
+               SysAssertf(!IsFailed(r), "[%s] Constructing the registry file (%ls) has failed.", GetErrorMessage(r), __regPath.GetPointer());
 
-       return r;
-
-CATCH:
-       delete __pRegistry;
-       __pRegistry = null;
+               FileLock* pReglock = reg.LockN(FILE_LOCK_EXCLUSIVE);
+               SysTryLog(NID_APP, pReglock != null, "[%s] Locking the app registry file has failed.", GetErrorMessage(GetLastResult()));
 
-       SysLog(NID_APP, "Exit.");
+               r = reg.AddSection(__sectionName);
+               if (r == E_SECTION_ALREADY_EXIST)
+               {
+                       r = E_SUCCESS;
+               }
 
+               reg.Flush();
+               delete pReglock;
+       }
        return r;
 }
 
-
 result
 _AppRegistryImpl::Add(const String& key, const String& value)
 {
-       SysAssertf(__pRegistry != null, "Not yet constructed. Construct() should be called before use.");
+       MutexGuard lock(__mutex);
 
-       result r = E_SUCCESS;
+       Registry* pReg = LoadN(ReadWrite);
+       if (pReg == null)
+       {
+               result r = GetLastResult();
+               SysPropagate(NID_APP, r);
+               return r;
+       }
 
-       r = __pRegistry->AddValue(__sectionName, key, value);
+       result r = pReg->AddValue(__sectionName, key, value);
+       SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Adding value to the registry has failed.", GetErrorMessage(r));
 
+       r = pReg->Flush();
        SysTryLog(NID_APP, !IsFailed(r), "[%s] Adding value to the registry has failed.", GetErrorMessage(r));
 
+CATCH:
+       delete pReg;
        return r;
 }
 
-
 result
 _AppRegistryImpl::Add(const String& key, int value)
 {
-       SysAssertf(__pRegistry != null, "Not yet constructed. Construct() should be called before use.");
+       MutexGuard lock(__mutex);
 
-       result r = E_SUCCESS;
+       Registry* pReg = LoadN(ReadWrite);
+       if (pReg == null)
+       {
+               result r = GetLastResult();
+               SysPropagate(NID_APP, r);
+               return r;
+       }
 
-       r = __pRegistry->AddValue(__sectionName, key, value);
+       result r = pReg->AddValue(__sectionName, key, value);
+       SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Adding value to the registry has failed.", GetErrorMessage(r));
 
+       r = pReg->Flush();
        SysTryLog(NID_APP, !IsFailed(r), "[%s] Adding value to the registry has failed.", GetErrorMessage(r));
 
+CATCH:
+       delete pReg;
        return r;
 }
 
-
 result
 _AppRegistryImpl::Add(const String& key, double value)
 {
-       SysAssertf(__pRegistry != null, "Not yet constructed. Construct() should be called before use.");
+       MutexGuard lock(__mutex);
 
-       result r = E_SUCCESS;
+       Registry* pReg = LoadN(ReadWrite);
+       if (pReg == null)
+       {
+               result r = GetLastResult();
+               SysPropagate(NID_APP, r);
+               return r;
+       }
 
-       r = __pRegistry->AddValue(__sectionName, key, value);
+       result r = pReg->AddValue(__sectionName, key, value);
+       SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Adding value to the registry has failed.", GetErrorMessage(r));
 
+       r = pReg->Flush();
        SysTryLog(NID_APP, !IsFailed(r), "[%s] Adding value to the registry has failed.", GetErrorMessage(r));
 
+CATCH:
+       delete pReg;
        return r;
 }
 
-
 result
 _AppRegistryImpl::Set(const String& key, const String& value)
 {
-       SysAssertf(__pRegistry != null, "Not yet constructed. Construct() should be called before use.");
+       MutexGuard lock(__mutex);
 
-       result r = E_SUCCESS;
+       Registry* pReg = LoadN(ReadWrite);
+       if (pReg == null)
+       {
+               result r = GetLastResult();
+               SysPropagate(NID_APP, r);
+               return r;
+       }
 
-       r = __pRegistry->SetValue(__sectionName, key, value);
+       result r = pReg->SetValue(__sectionName, key, value);
+       SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Setting value to the registry has failed.", GetErrorMessage(r));
 
+       r = pReg->Flush();
        SysTryLog(NID_APP, !IsFailed(r), "[%s] Setting value to the registry has failed.", GetErrorMessage(r));
 
+CATCH:
+       delete pReg;
        return r;
 }
 
-
 result
 _AppRegistryImpl::Set(const String& key, int value)
 {
-       SysAssertf(__pRegistry != null, "Not yet constructed. Construct() should be called before use.");
+       MutexGuard lock(__mutex);
 
-       result r = E_SUCCESS;
+       Registry* pReg = LoadN(ReadWrite);
+       if (pReg == null)
+       {
+               result r = GetLastResult();
+               SysPropagate(NID_APP, r);
+               return r;
+       }
 
-       r = __pRegistry->SetValue(__sectionName, key, value);
+       result r = pReg->SetValue(__sectionName, key, value);
+       SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Setting value to the registry has failed.", GetErrorMessage(r));
 
+       r = pReg->Flush();
        SysTryLog(NID_APP, !IsFailed(r), "[%s] Setting value to the registry has failed.", GetErrorMessage(r));
 
+CATCH:
+       delete pReg;
        return r;
 }
 
-
 result
 _AppRegistryImpl::Set(const String& key, double value)
 {
-       SysAssertf(__pRegistry != null, "Not yet constructed. Construct() should be called before use.");
+       MutexGuard lock(__mutex);
 
-       result r = E_SUCCESS;
+       Registry* pReg = LoadN(ReadWrite);
+       if (pReg == null)
+       {
+               result r = GetLastResult();
+               SysPropagate(NID_APP, r);
+               return r;
+       }
 
-       r = __pRegistry->SetValue(__sectionName, key, value);
+       result r = pReg->SetValue(__sectionName, key, value);
+       SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Setting value to the registry has failed.", GetErrorMessage(r));
 
+       r = pReg->Flush();
        SysTryLog(NID_APP, !IsFailed(r), "[%s] Setting value to the registry has failed.", GetErrorMessage(r));
 
+CATCH:
+       delete pReg;
        return r;
 }
 
-
 result
 _AppRegistryImpl::Save(void)
 {
-       SysAssertf(__pRegistry != null, "Not yet constructed. Construct() should be called before use.");
-
-       result r = E_SUCCESS;
-
-       r = __pRegistry->Flush();
-
-       SysTryLog(NID_APP, !IsFailed(r), "[%s] Saving value to the registry has failed.", GetErrorMessage(r));
-
-       return r;
+    return E_SUCCESS;
 }
 
-
 result
 _AppRegistryImpl::Remove(const String& key)
 {
-       SysAssertf(__pRegistry != null, "Not yet constructed. Construct() should be called before use.");
+       MutexGuard lock(__mutex);
 
-       result r = E_SUCCESS;
-
-       r = __pRegistry->RemoveValue(__sectionName, key);
+       Registry* pReg = LoadN(ReadWrite);
+       if (pReg == null)
+       {
+               result r = GetLastResult();
+               SysPropagate(NID_APP, r);
+               return r;
+       }
 
+       result r = pReg->RemoveValue(__sectionName, key);
        SysTryLog(NID_APP, !IsFailed(r), "[%s] Removing value to the registry has failed.", GetErrorMessage(r));
 
+       delete pReg;
+
        return r;
 }
 
-
 result
 _AppRegistryImpl::Get(const String& key, String& value) const
 {
-       SysAssertf(__pRegistry != null, "Not yet constructed. Construct() should be called before use.");
+       MutexGuard lock(__mutex);
 
-       result r = E_SUCCESS;
-
-       r = __pRegistry->GetValue(__sectionName, key, value);
+       Registry* pReg = LoadN(ReadOnly);
+       if (pReg == null)
+       {
+               result r = GetLastResult();
+               SysPropagate(NID_APP, r);
+               return r;
+       }
 
+       result r = pReg->GetValue(__sectionName, key, value);
        SysTryLog(NID_APP, !IsFailed(r), "[%s] Getting value to the registry has failed.", GetErrorMessage(r));
 
+       delete pReg;
+
        return r;
 }
 
-
 result
 _AppRegistryImpl::Get(const String& key, int& value) const
 {
-       SysAssertf(__pRegistry != null, "Not yet constructed. Construct() should be called before use.");
-
-       result r = E_SUCCESS;
+       MutexGuard lock(__mutex);
 
-       r = __pRegistry->GetValue(__sectionName, key, value);
+       Registry* pReg = LoadN(ReadOnly);
+       if (pReg == null)
+       {
+               result r = GetLastResult();
+               SysPropagate(NID_APP, r);
+               return r;
+       }
 
+       result r = pReg->GetValue(__sectionName, key, value);
        SysTryLog(NID_APP, !IsFailed(r), "[%s] Getting value to the registry has failed.", GetErrorMessage(r));
 
+       delete pReg;
+
        return r;
 }
 
-
 result
 _AppRegistryImpl::Get(const String& key, double& value) const
 {
-       SysAssertf(__pRegistry != null, "Not yet constructed. Construct() should be called before use.");
-
-       result r = E_SUCCESS;
+       MutexGuard lock(__mutex);
 
-       r = __pRegistry->GetValue(__sectionName, key, value);
+       Registry* pReg = LoadN(ReadOnly);
+       if (pReg == null)
+       {
+               result r = GetLastResult();
+               SysPropagate(NID_APP, r);
+               return r;
+       }
 
+       result r = pReg->GetValue(__sectionName, key, value);
        SysTryLog(NID_APP, !IsFailed(r), "[%s] Getting value to the registry has failed.", GetErrorMessage(r));
 
+       delete pReg;
+
        return r;
 }
 
+Registry*
+_AppRegistryImpl::LoadN(ReadOnlyTag) const
+{
+       Registry* pReg = new (std::nothrow) Registry();
+       SysTryReturn(NID_APP, pReg != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
+
+       result r = pReg->Construct(__regPath, "r");
+       SysAssertf(!IsFailed(r), "Constructing the registry file (%ls) has failed. %s occurred.",
+                       __regPath.GetPointer(), GetErrorMessage(r));
+
+       SetLastResult(r);
+       return pReg;
+}
+
+Registry*
+_AppRegistryImpl::LoadN(ReadWriteTag) const
+{
+       Registry* pReg = new (std::nothrow) Registry();
+       SysTryReturn(NID_APP, pReg != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
+
+       result r = pReg->Construct(__regPath, "a+");
+       SysAssertf(!IsFailed(r), "Constructing the registry file (%ls) has failed. %s occurred.",
+                       __regPath.GetPointer(), GetErrorMessage(r));
+
+       SetLastResult(r);
+       return pReg;
+}
+
+}} // Tizen::App
 
-} } // Tizen::App