proper headers
[platform/framework/native/appfw.git] / src / app / FApp_MapDataControlImpl.cpp
index 9ac9ab2..7ee27e4 100644 (file)
@@ -1,5 +1,4 @@
 //
-// Open Service Platform
 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
 //
 // Licensed under the Apache License, Version 2.0 (the License);
  */
 
 #include <typeinfo>
-#include <new>
 #include <unique_ptr.h>
 
 #include <appsvc/appsvc.h>
 
 #include <FBaseInteger.h>
 #include <FBaseString.h>
+#include <FBaseColLinkedList.h>
 #include <FBaseRtIEventArg.h>
+#include <FIoFile.h>
 #include <FAppMapDataControl.h>
 #include <FAppIMapDataControlResponseListener.h>
 
@@ -51,6 +51,7 @@ namespace Tizen { namespace App
 {
 
 static const int MAX_REQUEST_COUNT = 128;
+static const int REQUEST_THRESHOLD = 100;
 static const int _MAX_ARGUMENT_SIZE = 16384; // 16KB
 
 class _MapDataControlEventArg
@@ -91,7 +92,7 @@ class _MapDataControlEvent
        : public Event
 {
 protected:
-               virtual void FireImpl(IEventListener& listener, const IEventArg& arg);
+       virtual void FireImpl(IEventListener& listener, const IEventArg& arg);
 };
 
 void
@@ -130,9 +131,7 @@ _MapDataControlEvent::FireImpl(IEventListener& listener, const IEventArg& arg)
 
 // private
 _MapDataControlImpl::_MapDataControlImpl(void)
-       : __appId(L"")
-       , __providerId(L"")
-       , __access(_DATACONTROL_ACCESS_UNDEFINED)
+       : __access(_DATACONTROL_ACCESS_UNDEFINED)
        , __pPreviousListener(null)
        , __pMapDataControlEvent(null)
 {
@@ -141,6 +140,19 @@ _MapDataControlImpl::_MapDataControlImpl(void)
 _MapDataControlImpl::~_MapDataControlImpl(void)
 {
        delete __pMapDataControlEvent;
+
+       _DataControlManager* pDcMgr = _DataControlManager::GetInstance();
+
+       IEnumerator* pEnum = __pRequestList->GetEnumeratorN();
+       while (pEnum->MoveNext() == E_SUCCESS)
+       {
+               Integer* pReqId = dynamic_cast< Integer* >(pEnum->GetCurrent());
+               if (pReqId != null)
+               {
+                       pDcMgr->RemoveRequestInfo(*pReqId);
+               }
+       }
+       delete __pRequestList;
 }
 
 _MapDataControlImpl*
@@ -163,12 +175,25 @@ _MapDataControlImpl::StartMapDataControl(int type, const IList* pDataList, int*
        result r = E_SUCCESS;
 
        int req = -1;
-       _AppControlManager* pAppManagerImpl = _AppControlManager::GetInstance();
+       _DataControlManager* pDcMgr = _DataControlManager::GetInstance();
 
        // Check the request count of DataControl operation
-       int count = pAppManagerImpl->GetLaunchRequestCount();
+       int count = pDcMgr->GetRequestCount();
        SysLog(NID_APP, "Current launch request count: %d", count);
 
+       if (count > REQUEST_THRESHOLD)
+       {
+               _AppManagerImpl* pImpl = _AppManagerImpl::GetInstance();
+
+               // Clear the request queue if the provider is terminated
+               if (!pImpl->IsRunning(__appId))
+               {
+                       SysLog(NID_APP, "The request queue is cleared due to the invalid provider.");
+
+                       pDcMgr->RemoveAllRequests();
+               }
+       }
+
        SysTryReturnResult(NID_APP, count < MAX_REQUEST_COUNT, E_MAX_EXCEEDED, "The number of requests has exceeded the maximum limit.");
 
        _AppArg* pArg = new(std::nothrow) _AppArg; // XXX: pArg will be released in _AppManagerImpl::LaunchApp().
@@ -176,6 +201,8 @@ _MapDataControlImpl::StartMapDataControl(int type, const IList* pDataList, int*
 
        pArg->Construct(*this, static_cast <_DataControlRequestType>(type), pDataList);
 
+       _AppControlManager* pAppManagerImpl = _AppControlManager::GetInstance();
+
        if (__pMapDataControlEvent)
        {
                // reqId is system-wide id because the bundle is system-wide.
@@ -192,8 +219,9 @@ _MapDataControlImpl::StartMapDataControl(int type, const IList* pDataList, int*
                                "[E_OUT_OF_MEMORY] The memory is insufficient");
 
                pReqInfo = new (std::nothrow) _DataControlRequestInfo(__pMapDataControlEvent);
-               SysTryCatch(NID_APP, pReqId != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
+               SysTryCatch(NID_APP, pReqInfo != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
                                "[E_OUT_OF_MEMORY] The memory is insufficient");
+               pReqInfo->SetMapDataControlImpl(this);
 
                r = pDcMgr->AddRequestInfo(pReqId, pReqInfo);
                SysTryCatch(NID_APP, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[%s] Failed to add request info", GetErrorMessage(r));
@@ -204,10 +232,11 @@ _MapDataControlImpl::StartMapDataControl(int type, const IList* pDataList, int*
                        SysPropagate(NID_APP, r);
                        reqObj.Invalidate();
                        pDcMgr->RemoveRequestInfo(*pReqId);
-                       delete pArg;
                        return r;
                }
 
+               __pRequestList->Add(new (std::nothrow) Integer(req));
+
                if (pReq)
                {
                        *pReq = req;
@@ -251,7 +280,7 @@ _MapDataControlImpl::GetValue(const String& dataId, const String& key,
        long long argSize = dataId.GetLength() * sizeof(wchar_t);
        argSize += key.GetLength() * sizeof(wchar_t);
        SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
-                       "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
+                       "[E_MAX_EXCEEDED] The size of sending argument (%lld) exceeds the maximum limit.", argSize);
 
        pPageNo = new (std::nothrow) String();
        pPageNo->Append(pageNo);
@@ -266,7 +295,7 @@ _MapDataControlImpl::GetValue(const String& dataId, const String& key,
 
        reqId = static_cast< RequestId >(id);
 
-       SysLog(NID_APP, "[DC_CALLER_SEND] dataId: %ls, key: %ls, reqId: %d, pageNo: %d, countPerPage: %d",
+       SysLog(NID_APP, "[DC_CALLER_SEND] data: %ls, key: %ls, req: %d, pageNo: %d, countPerPage: %d",
                        dataId.GetPointer(), key.GetPointer(), reqId, pageNo, countPerPage);
 
        // fall through
@@ -278,25 +307,28 @@ CATCH:
 }
 
 result
-_MapDataControlImpl::MapDataControlCallback(void* data, _AppArg* pArg, _AppArg* pResArg, service_result_e res, int prop)
+_MapDataControlImpl::MapDataControlCallback(void* data, _AppArg* pArg, _AppArg* pResArg, service_result_e res, int prop, int option)
 {
        ArrayList* pResultList = null;
+       String version;
        String* pResult = null;
        String* pProviderId = null;
        String* pDataId = null;
        String* pErrorMessage = null;
        String* pErrorMsg = null;
        String* pResultCount = null;
-       String* pValue = null;
+       String* pPath = null;
        ArrayList* pResultValueList = null;
        int resultCount = 0;
        int requestType = 0;
        int reqId = 0;
+       int launchReqId = 0;
        int providerRes = 0;
        bool providerResult = true;
        //bundle* origBundle = null;
        bundle* resBundle = null;
        _MapDataControlEventArg* pEventArg = null;
+       const char* p = null;
        result r = E_SUCCESS;
 
        SysTryReturnResult(NID_APP, pResArg != null, E_INVALID_ARG, "Empty result callback.");
@@ -305,22 +337,31 @@ _MapDataControlImpl::MapDataControlCallback(void* data, _AppArg* pArg, _AppArg*
        resBundle = pResArg->GetBundle();
        if (resBundle)
        {
-               const char* p = appsvc_get_data(resBundle, OSP_K_REQUEST_ID);
+               p = appsvc_get_data(resBundle, OSP_K_REQUEST_ID);
                SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
                reqId = atoi(p);
                Integer key(reqId);
 
                _DataControlManager* pDcMgr = static_cast< _DataControlManager* >(data);
                _DataControlRequestInfo* pReqInfo = pDcMgr->GetRequestInfo(key);
-               SysTryCatch(NID_APP, pReqInfo != null, r = E_SYSTEM, E_SYSTEM,
-                               "[E_SYSTEM] Failed to get request info");
+               if (pReqInfo == null)
+               {
+                       SysLog(NID_APP, "No request info of reqId %d", reqId);
+                       return E_SUCCESS;
+               }
 
                _MapDataControlEvent* pMapDataControlEvent = dynamic_cast< _MapDataControlEvent* >(pReqInfo->GetEvent());
-               SysTryCatch(NID_APP, pMapDataControlEvent != null, r = E_SYSTEM, E_SYSTEM,
-                               "[E_SYSTEM] invalid request info");
+               SysTryCatch(NID_APP, pMapDataControlEvent != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid request info");
 
                pDcMgr->RemoveRequestInfo(key);
 
+               _MapDataControlImpl* pDcImpl = pReqInfo->GetMapDataControlImpl();
+               SysTryCatch(NID_APP, pDcImpl != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid request info");
+               pDcImpl->__pRequestList->Remove(key);
+
+               // Remove the request from the queue
+               SysLog(NID_APP, "Remove the request, req: %d", reqId);
+
                if (pMapDataControlEvent != null && typeid(pMapDataControlEvent) == typeid(_MapDataControlEvent*))
                {
 
@@ -358,44 +399,87 @@ _MapDataControlImpl::MapDataControlCallback(void* data, _AppArg* pArg, _AppArg*
                        SysTryCatch(NID_APP, pDataId, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
                                        "[E_OUT_OF_MEMORY] The memory is insufficient.");
 
-                       SysLog(NID_APP, "[DC_CALLER_RECV] provider result: %ld, requestType: %d, reqId: %d, providerId: %ls, dataId: %ls, errorMsg: %ls ",
-                                       providerRes, requestType, reqId, pProviderId->GetPointer(), pDataId->GetPointer(), pErrorMsg->GetPointer());
+                       version = pResArg->GetValue(OSP_K_DATACONTROL_PROTOCOL_VERSION);
+
+                       SysSecureLog(NID_APP, "[DC_CALLER_RECV] version: %ls, provider result: %ld, requestType: %d, req: %d, provider: %ls, data: %ls, errorMsg: %ls",
+                                       version.GetPointer(), providerRes, requestType, reqId, pProviderId->GetPointer(), pDataId->GetPointer(), pErrorMsg->GetPointer());
 
                        switch (static_cast< _DataControlRequestType >(requestType))
                        {
                        case _DATACONTROL_REQUEST_TYPE_MAP_QUERY:
                        {
-                               pResultValueList = new (std::nothrow) ArrayList();
+                               pResultValueList = new (std::nothrow) ArrayList(SingleObjectDeleter);
                                SysTryCatch(NID_APP, pResultValueList, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
                                                "[E_OUT_OF_MEMORY] The memory is insufficient.");
 
                                if (providerResult == true)
                                {
                                        pResultCount = dynamic_cast< String* >(pResultList->GetAt(2)); // result list[2]
-                                       if (pResultCount == null)
-                                       {
-                                               SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] invalid result");
-                                               pResultValueList->RemoveAll(true);
-                                               delete pResultValueList;
-                                               goto CATCH;
-                                       }
+                                       SysTryCatch(NID_APP, pResultCount, delete pResultValueList, E_SYSTEM, "[E_SYSTEM] invalid result");
                                        Integer::Parse(*pResultCount, resultCount);
+                                       SysLog(NID_APP, "[DC_CALLER_RECV] result count: %d", resultCount);
 
-                                       int index = 3;
-                                       while (resultCount)
+                                       if (resultCount > 0)
                                        {
-                                               pValue = dynamic_cast< String* >(pResultList->GetAt(index));
-                                               if (pValue == null)
+                                               if (version == L"ver_2.1.0.1" || version == L"ver_2.1.0.2" || version == L"ver_2.1.0.3")
                                                {
-                                                       SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] invalid result");
-                                                       pResultValueList->RemoveAll(true);
-                                                       delete pResultValueList;
-                                                       goto CATCH;
+                                                       pPath = dynamic_cast< String* >(pResultList->GetAt(3)); // result list[3]
+                                                       SysTryCatch(NID_APP, pPath, delete pResultValueList, E_SYSTEM, "[E_SYSTEM] invalid result");
+                                                       SysLog(NID_APP, "[DC_CALLER_RECV] path: %ls", pPath->GetPointer());
+
+                                                       unique_ptr< File > pFile(new (std::nothrow) File());
+                                                       SysTryCatch(NID_APP, pFile, delete pResultValueList, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
+
+                                                       r = pFile->Construct(*pPath, "r");
+                                                       SysTryCatch(NID_APP, !IsFailed(r), delete pResultValueList, r, "[%s] Failed to open result set (%ls)",
+                                                                       GetErrorMessage(r), pPath->GetPointer());
+
+                                                       while (resultCount)
+                                                       {
+                                                               int length = 0;
+                                                               int ret = pFile->Read(&length, sizeof(int));
+                                                               SysTryCatch(NID_APP, ret, delete pResultValueList, E_SYSTEM,
+                                                                               "[E_SYSTEM] Failed to read data from the result set of data control provider.");
+
+                                                               char* pValue = new (std::nothrow) char[length + 1];
+                                                               SysTryCatch(NID_APP, pValue, delete pResultValueList, E_OUT_OF_MEMORY,
+                                                                               "[E_OUT_OF_MEMORY] The memory is insufficient.");
+
+                                                               ret = pFile->Read(pValue, length);
+                                                               if (ret == 0)
+                                                               {
+                                                                       SysLogException(NID_APP, E_SYSTEM,
+                                                                                       "[E_SYSTEM] Failed to read data from the result set of data control provider.");
+                                                                       delete pResultValueList;
+                                                                       delete[] pValue;
+                                                                       goto CATCH;
+                                                               }
+                                                               pValue[length] = '\0';
+
+                                                               pResultValueList->Add(new (std::nothrow) String(pValue));
+                                                               delete[] pValue;
+                                                               --resultCount;
+                                                       }
                                                }
+                                               else
+                                               {
+                                                       int index = 3;
+                                                       while (resultCount)
+                                                       {
+                                                               String* pValue = dynamic_cast< String* >(pResultList->GetAt(index)); // result list[3] ~
+                                                               SysTryCatch(NID_APP, pValue, delete pResultValueList, E_SYSTEM, "[E_SYSTEM] invalid result");
+
+                                                               pResultValueList->Add((new (std::nothrow) String(*pValue)));
+                                                               --resultCount;
+                                                               ++index;
+                                                       }
+                                               }
+                                       }
 
-                                               pResultValueList->Add(*(new (std::nothrow) String(*pValue)));
-                                               resultCount--;
-                                               index++;
+                                       if (pPath)
+                                       {
+                                               r = File::Remove(*pPath);
+                                               SysTryLog(NID_APP, !IsFailed(r), "Failed to remove result: %ls", pPath->GetPointer());
                                        }
                                }
 
@@ -440,9 +524,9 @@ _MapDataControlImpl::MapDataControlCallback(void* data, _AppArg* pArg, _AppArg*
                }
        }
 
-       // Remove the request count
-       SysLog(NID_APP, "Remove a launch request: reqId: %d", reqId);
-       _AppControlManager::GetInstance()->RemoveLaunchRequest(reqId);
+       p = appsvc_get_data(pArg->GetBundle(), OSP_K_REQUEST_ID);
+       SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
+       launchReqId = atoi(p);
 
        return E_SUCCESS;
 
@@ -478,14 +562,14 @@ _MapDataControlImpl::AddValue(const String& dataId, const String& key,
        argSize += key.GetLength() * sizeof(wchar_t);
        argSize += value.GetLength() * sizeof(wchar_t);
        SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
-                       "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
+                       "[E_MAX_EXCEEDED] The size of sending argument (%lld) exceeds the maximum limit.", argSize);
 
        r = StartMapDataControl(_DATACONTROL_REQUEST_TYPE_MAP_INSERT, pArgList, &id);
        SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
 
        reqId = static_cast< RequestId >(id);
 
-       SysLog(NID_APP, "[DC_CALLER_SEND] dataId: %ls, key: %ls, value: %ls, reqId: %d",
+       SysLog(NID_APP, "[DC_CALLER_SEND] data: %ls, key: %ls, value: %ls, req: %d",
                        dataId.GetPointer(), key.GetPointer(), value.GetPointer(), reqId);
 
        // fall through
@@ -519,14 +603,14 @@ _MapDataControlImpl::SetValue(const String& dataId, const String& key,
        argSize += oldValue.GetLength() * sizeof(wchar_t);
        argSize += newValue.GetLength() * sizeof(wchar_t);
        SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
-                       "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
+                       "[E_MAX_EXCEEDED] The size of sending argument (%lld) exceeds the maximum limit.", argSize);
 
        r = StartMapDataControl(_DATACONTROL_REQUEST_TYPE_MAP_UPDATE, pArgList, &id);
        SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
 
        reqId = static_cast< RequestId >(id);
 
-       SysLog(NID_APP, "[DC_CALLER_SEND] dataId: %ls, key: %ls, oldValue: %ls, newValue: %ls, reqId: %d",
+       SysLog(NID_APP, "[DC_CALLER_SEND] data: %ls, key: %ls, oldValue: %ls, newValue: %ls, req: %d",
                        dataId.GetPointer(), key.GetPointer(), oldValue.GetPointer(), newValue.GetPointer(), reqId);
 
        // fall through
@@ -558,14 +642,14 @@ _MapDataControlImpl::RemoveValue(const String& dataId, const String& key,
        argSize += key.GetLength() * sizeof(wchar_t);
        argSize += value.GetLength() * sizeof(wchar_t);
        SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
-                       "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
+                       "[E_MAX_EXCEEDED] The size of sending argument (%lld) exceeds the maximum limit.", argSize);
 
        r = StartMapDataControl(_DATACONTROL_REQUEST_TYPE_MAP_DELETE, pArgList, &id);
        SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
 
        reqId = static_cast< RequestId >(id);
 
-       SysLog(NID_APP, "[DC_CALLER_SEND] dataId: %ls, key: %ls, value: %ls, reqId: %d",
+       SysLog(NID_APP, "[DC_CALLER_SEND] data: %ls, key: %ls, value: %ls, req: %d",
                        dataId.GetPointer(), key.GetPointer(), value.GetPointer(), reqId);
 
        // fall through
@@ -620,12 +704,15 @@ _MapDataControlImpl::CreateMapDataControl(const AppId& appId, const String& prov
        SysTryReturn(NID_APP, pDc != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient");
 
        _MapDataControlImpl* pDcImpl = _MapDataControlImpl::GetInstance(*pDc);
+       pDcImpl->__appId = appId;
+       pDcImpl->__providerId = providerId;
        unique_ptr<_MapDataControlEvent> pMapDataControlEvent(new (std::nothrow) _MapDataControlEvent);
        SysTryReturn(NID_IO, pMapDataControlEvent != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
 
+       pDcImpl->__pRequestList = new (std::nothrow) LinkedList(SingleObjectDeleter);
+       SysTryReturn(NID_IO, pDcImpl->__pRequestList != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
+
        pDcImpl->__pMapDataControlEvent = pMapDataControlEvent.release();
-       pDcImpl->__appId = appId;
-       pDcImpl->__providerId = providerId;
 
        if (access == L"readonly")
        {