Increase result set size of MapDataControl
[platform/framework/native/appfw.git] / src / app / FApp_DataControlProviderManagerImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        FApp_DataControlProviderManagerImpl.cpp
20  * @brief       This is the implementation for the %_DataControlProviderManagerImpl class.
21  */
22
23 #include <new>
24 #include <unique_ptr.h>
25
26 #include <FBaseDataType.h>
27 #include <FBaseInteger.h>
28 #include <FBaseString.h>
29 #include <FBaseLongLong.h>
30 #include <FBaseColArrayList.h>
31 #include <FBaseColIList.h>
32 #include <FBaseSysLog.h>
33 #include <FBaseErrors.h>
34 #include <FAppAppManager.h>
35 #include <FAppSqlDataControl.h>
36 #include <FAppMapDataControl.h>
37 #include <FAppDataControlProviderManager.h>
38 #include <FIoFile.h>
39
40 #include <FBase_StringConverter.h>
41 #include <FIo_DataControlResultSetImpl.h>
42
43 #include "FApp_Aul.h"
44 #include "FApp_AppArg.h"
45 #include "FApp_AppInfo.h"
46 #include "FApp_AppImpl.h"
47 #include "FApp_AppControlManager.h"
48 #include "FApp_SqlDataControlImpl.h"
49 #include "FApp_MapDataControlImpl.h"
50 #include "FApp_DataControlProviderManagerImpl.h"
51
52 using namespace std;
53 using namespace Tizen::Base;
54 using namespace Tizen::Base::Collection;
55 using namespace Tizen::Io;
56
57 extern const char* _DATACONTROL_RESULTSET_DIR;
58
59 namespace Tizen { namespace App
60 {
61
62 static const int _MAX_ARGUMENT_SIZE = 16384; // 16KB
63
64 result
65 _DataControlProviderManagerImpl::SetSqlDataControlProviderEventListener(ISqlDataControlProviderEventListener* pListener)
66 {
67         _AppImpl* pAppImpl = _AppImpl::GetInstance();
68         SysTryReturn(NID_APP, pAppImpl, false, E_INVALID_STATE, "[E_INVALID_STATE] Getting _AppImpl instance failed.");
69
70         return pAppImpl->SetSqlDataControlProviderEventListener(pListener);
71 }
72
73 result
74 _DataControlProviderManagerImpl::SetMapDataControlProviderEventListener(IMapDataControlProviderEventListener* pListener)
75 {
76         _AppImpl* pAppImpl = _AppImpl::GetInstance();
77         SysTryReturn(NID_APP, pAppImpl, false, E_INVALID_STATE, "[E_INVALID_STATE] Getting _AppImpl instance failed.");
78
79         return pAppImpl->SetMapDataControlProviderEventListener(pListener);
80 }
81
82 result
83 _DataControlProviderManagerImpl::SendDataControlResult(RequestId reqId, _DataControlRequestType apiType,
84                 IDbEnumerator* pDbEnum, IList* pResultValueList, long long insertRowId, bool providerResult, const String* pErrorMsg)
85 {
86         ArrayList* pList = null;
87         String callerAppId;
88         int callerPid = -1;
89         String version;
90         String reqType;
91         int type = 0;
92         _DataControlRequestType requestType = _DATACONTROL_REQUEST_TYPE_UNDEFINED;
93         String providerId;
94         String callerReqId;
95         ArrayList* pResultArgList = null;
96         String* pResult = null;
97         String* pErrorMessage = null;
98         String* pTempFilePath = null;
99         String* pNo = null;
100         int pageNo = 0;
101         String* pCount = null;
102         int countPerPage = 0;
103         String* pResultCount = null;
104         String* pResultValue = null;
105         _AppArg resultArg;
106         String* pDataId = null;
107         result r = E_SUCCESS;
108
109         _AppControlManager* pAppMgr = _AppControlManager::GetInstance();
110         SysTryReturnResult(NID_APP, pAppMgr, E_SYSTEM, "Failed to get instance.");
111
112         _ResultInfo* pResultInfo = pAppMgr->__resultManager.FindItem(static_cast< int >(reqId)); // provider reqId
113         SysTryReturnResult(NID_APP, pResultInfo, E_OBJ_NOT_FOUND,
114                         "The data control request specified with the req (%ld) did not exist.", reqId);
115
116         const _AppArg& arg = pResultInfo->arg; // request info
117
118         // key-based request
119         reqType = arg.GetValue(OSP_K_DATACONTROL_REQUEST_TYPE);
120         Integer::Parse(reqType, type);
121         requestType = static_cast< _DataControlRequestType >(type);
122         if (providerResult == true && apiType != requestType)
123         {
124                 if ((apiType == _DATACONTROL_REQUEST_TYPE_SQL_UPDATE /*UpdateDelete*/ && requestType == _DATACONTROL_REQUEST_TYPE_SQL_DELETE) ||
125                                 apiType == _DATACONTROL_REQUEST_TYPE_UNDEFINED /*MAP*/)
126                 {
127                         r = E_SUCCESS;
128                 }
129                 else
130                 {
131                         r = E_INVALID_ARG;
132                         SysLog(NID_APP, "[E_INVALID_ARG] This method cannot send the result set for the specified reqId.");
133                         goto CATCH;
134                 }
135         }
136
137         callerAppId = arg.GetCallerAppId();
138         callerPid = arg.GetCallerPid();
139         version = arg.GetValue(OSP_K_DATACONTROL_PROTOCOL_VERSION);
140         callerReqId = arg.GetValue(OSP_K_REQUEST_ID);
141         providerId = arg.GetValue(OSP_K_DATACONTROL_PROVIDER);
142
143         // list-based request
144         pList = _AppArg::GetListN(arg.GetBundle(), OSP_K_ARG);
145         SysTryCatch(NID_APP, pList, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
146
147         pDataId = dynamic_cast< String* >(pList->GetAt(0)); // request list[0]
148         SysTryCatch(NID_APP, pDataId, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
149
150         SysLog(NID_APP, "[DC_PROV_SEND] > caller app: %ls, caller proc: %d, version: %ls requestType: %d, callerReq: %ls, provider: %ls, data: %ls",
151                         callerAppId.GetPointer(), callerPid, version.GetPointer(), requestType, callerReqId.GetPointer(), providerId.GetPointer(), pDataId->GetPointer());
152
153         // Serializes result
154         pResultArgList = new (std::nothrow) ArrayList();
155         SysTryCatch(NID_APP, pResultArgList, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
156                         "[E_OUT_OF_MEMORY] The memory was insufficient.");
157         pResultArgList->Construct();
158
159         pResult = new (std::nothrow) String();
160         SysTryCatch(NID_APP, pResult, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
161                         "[E_OUT_OF_MEMORY] The memory was insufficient.");
162         pResult->Append(static_cast< int >(providerResult));
163         pResultArgList->Add(*pResult); // result list[0]
164
165         if (pErrorMsg == null)
166         {
167                 pErrorMessage = new (std::nothrow) String();
168         }
169         else
170         {
171                 pErrorMessage = new (std::nothrow) String(*pErrorMsg);
172         }
173         SysTryCatch(NID_APP, pErrorMessage, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
174                         "[E_OUT_OF_MEMORY] The memory was insufficient.");
175         SysTryCatch(NID_APP, pErrorMessage->GetLength() <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
176                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", pErrorMessage->GetLength());
177         pResultArgList->Add(*pErrorMessage); // result list[1]
178
179         switch (requestType)
180         {
181         case _DATACONTROL_REQUEST_TYPE_SQL_QUERY:
182         {
183                 if (pDbEnum)
184                 {
185                         unique_ptr<_DataControlResultSetImpl> pResultSet(new (std::nothrow) _DataControlResultSetImpl(reqId));
186                         SysTryCatch(NID_APP, pResultSet, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
187                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
188
189                         r = pResultSet->FillWith(pDbEnum);
190                         SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM,
191                                         "[E_SYSTEM] The method cannot proceed due to a severe system error.");
192
193                         String tempFilePath(_DATACONTROL_RESULTSET_DIR);
194                         tempFilePath.Append(callerAppId);
195                         tempFilePath.Append(callerReqId);
196                         pTempFilePath = new (std::nothrow) String(tempFilePath);
197                 }
198                 else
199                 {
200                         pTempFilePath = new (std::nothrow) String(L"NoResultSet");
201                 }
202                 SysTryCatch(NID_APP, pTempFilePath, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
203                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
204
205                 pResultArgList->Add(*pTempFilePath); // result list[2]
206                 break;
207         }
208         case _DATACONTROL_REQUEST_TYPE_SQL_INSERT:
209                 pResultArgList->Add(*(new String(LongLong::ToString(insertRowId)))); // result list[2]
210                 break;
211
212         case _DATACONTROL_REQUEST_TYPE_SQL_UPDATE:
213                 // fall through
214         case _DATACONTROL_REQUEST_TYPE_SQL_DELETE:
215                 break;
216
217         case _DATACONTROL_REQUEST_TYPE_MAP_QUERY:
218         {
219                 SysTryCatch(NID_APP, !(providerResult == true && pResultValueList == null), r = E_INVALID_ARG, E_INVALID_ARG,
220                                 "[E_INVALID_ARG] The specified pResultValueList should not be null if the request is GetValue query.");
221
222                 if (pResultValueList)
223                 {
224                         // list-based request
225                         pNo = dynamic_cast< String* >(pList->GetAt(2)); // request list[2]
226                         SysTryCatch(NID_APP, pNo, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
227                         Integer::Parse(*pNo, pageNo);
228
229                         pCount = dynamic_cast< String* >(pList->GetAt(3)); // request list[3]
230                         SysTryCatch(NID_APP, pCount, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
231                         Integer::Parse(*pCount, countPerPage);
232                         SysLog(NID_APP, "[DC_PROV_SEND] pageNo: %d, countPerPage: %d", pageNo, countPerPage);
233
234                         String resultCount;
235                         int num = pResultValueList->GetCount();
236                         int currentoffset = (pageNo - 1) * countPerPage;
237                         int remainingNum = num - currentoffset;
238                         remainingNum = (remainingNum > 0) ? remainingNum : 0; // round off to zero if negative num is found
239                         int addItemCount = (countPerPage > remainingNum) ? remainingNum : countPerPage;
240                         resultCount.Append(addItemCount);
241
242                         pResultCount = new (std::nothrow) String(resultCount);
243                         SysTryCatch(NID_APP, pResultCount, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
244                                         "[E_OUT_OF_MEMORY] The memory was insufficient.");
245                         pResultArgList->Add(*pResultCount); // result list[2]
246                         SysLog(NID_APP, "[DC_PROV_SEND] result count: %ls", resultCount.GetPointer());
247
248                         long long argSize = 0;
249                         if (addItemCount > 0)
250                         {
251                                 if (version == L"ver_2.1.0.1")
252                                 {
253                                         String tempFilePath(_DATACONTROL_RESULTSET_DIR);
254                                         tempFilePath.Append(callerAppId);
255                                         tempFilePath.Append(callerReqId);
256                                         pTempFilePath = new (std::nothrow) String(tempFilePath);
257                                         pResultArgList->Add(*pTempFilePath); // result list[3]
258                                         SysLog(NID_APP, "[DC_PROV_SEND] protocol version: %ls, path: %ls", version.GetPointer(), pTempFilePath->GetPointer());
259
260                                         unique_ptr< File > pFile(new (std::nothrow) File());
261                                         SysTryCatch(NID_APP, pFile != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
262
263                                         r = pFile->Construct(*pTempFilePath, L"w+", true);
264                                         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Failed to create temp file (%ls) for result set.",
265                                                         GetErrorMessage(r), pTempFilePath->GetPointer());
266
267                                         for (int i = currentoffset; i < num; ++i)
268                                         {
269                                                 String* pValue = dynamic_cast< String* >(pResultValueList->GetAt(i));
270                                                 SysTryCatch(NID_APP, pValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
271                                                                 "[E_INVALID_ARG] The specified pResultValueList parameter should be String class.");
272
273                                                 int length = pValue->GetLength();
274                                                 r = pFile->Write(&length, sizeof(int)); // data length
275                                                 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] Failed to write result.", GetErrorMessage(r));
276
277                                                 unique_ptr< char[] > pData(_StringConverter::CopyToCharArrayN(*pValue));
278                                                 SysTryCatch(NID_APP, pData != null, , GetLastResult(), "[%s] Invalid result value",
279                                                                 GetErrorMessage(GetLastResult()));
280
281                                                 r = pFile->Write(pData.get(), strlen(pData.get())); // data
282                                                 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[E_SYSTEM] Failed to write result.", GetErrorMessage(r));
283                                                 argSize += pValue->GetLength() * sizeof(wchar_t);
284                                         }
285                                         pFile->Flush();
286                                 }
287                                 else
288                                 {
289                                         SysLog(NID_APP, "[DC_PROV_SEND] protocol version: none");
290                                         for (int i = currentoffset; i < num; ++i)
291                                         {
292                                                 String* pValue = dynamic_cast< String* >(pResultValueList->GetAt(i));
293                                                 SysTryCatch(NID_APP, pValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
294                                                                 "[E_INVALID_ARG] The specified pResultValueList parameter should be String class.");
295
296                                                 pResultValue = new (std::nothrow) String(*pValue);
297                                                 SysTryCatch(NID_APP, pResultValue, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
298                                                                 "[E_OUT_OF_MEMORY] The memory was insufficient.");
299                                                 pResultArgList->Add(*pResultValue); // list[3] ~
300                                                 argSize += pValue->GetLength() * sizeof(wchar_t);
301                                         }
302                                 }
303                         }
304                         SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
305                                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
306                 }
307                 break;
308         }
309         case _DATACONTROL_REQUEST_TYPE_MAP_INSERT:
310                 // fall through
311         case _DATACONTROL_REQUEST_TYPE_MAP_UPDATE:
312                 // fall through
313         case _DATACONTROL_REQUEST_TYPE_MAP_DELETE:
314                 SysTryCatch(NID_APP, !(providerResult == true && pResultValueList != null), r = E_INVALID_ARG, E_INVALID_ARG,
315                                 "[E_INVALID_ARG] The specified pResultValueList should be null if the request is \
316                                 one of AddValue, SetValue, RemoveValue queries.");
317                 break;
318
319         default:
320                 SysTryCatch(NID_APP, false, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result object");
321                 break;
322         }
323
324         r = resultArg.ConstructResult(arg, pResultArgList);
325         SysTryCatch(NID_APP, !IsFailed(r), r = E_SYSTEM, r, "[%s] Propagating.", GetErrorMessage(r));
326         resultArg.UpdateKeyValue(OSP_K_REQUEST_ID, callerReqId);
327         resultArg.UpdateKeyValue(OSP_K_DATACONTROL_REQUEST_TYPE, reqType);
328         resultArg.UpdateKeyValue(OSP_K_DATACONTROL_PROVIDER, providerId);
329         resultArg.UpdateKeyValue(OSP_K_DATACONTROL_DATA, *pDataId);
330         resultArg.UpdateKeyValue(OSP_K_DATACONTROL_PROTOCOL_VERSION, version);
331
332         //resultArg.Print();
333         r = _Aul::SendResult(resultArg.GetBundle(), static_cast< appsvc_result_val >(0));
334         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Failed to send result.", GetErrorMessage(r));
335
336         // Erases _AppArg after sending the result back to the caller
337         pAppMgr->__resultManager.RemoveItem(static_cast< int >(reqId));
338
339 CATCH:
340         if (pList)
341         {
342                 pList->RemoveAll(true);
343         }
344         delete pList;
345
346         if (pResultArgList)
347         {
348                 pResultArgList->RemoveAll(true);
349         }
350         delete pResultArgList;
351
352         return r;
353 }
354
355 result
356 _DataControlProviderManagerImpl::SendSqlDataControlSelectResult(RequestId reqId, IDbEnumerator* pDbEnum)
357 {
358         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_SQL_QUERY,
359                         pDbEnum, null, -1, true, null);
360 }
361
362 result
363 _DataControlProviderManagerImpl::SendSqlDataControlInsertResult(RequestId reqId, long long insertRowId)
364 {
365         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_SQL_INSERT,
366                         null, null, insertRowId, true, null);
367 }
368
369 result
370 _DataControlProviderManagerImpl::SendSqlDataControlUpdateDeleteResult(RequestId reqId)
371 {
372         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_SQL_UPDATE,
373                         null, null, -1, true, null);
374 }
375
376 result
377 _DataControlProviderManagerImpl::SendMapDataControlResult(RequestId reqId, IList* pResultValueList)
378 {
379         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_UNDEFINED,
380                         null, pResultValueList, -1, true, null);
381 }
382
383 result
384 _DataControlProviderManagerImpl::SendDataControlError(RequestId reqId, const String& errorMsg)
385 {
386         return _DataControlProviderManagerImpl::SendDataControlResult(reqId, _DATACONTROL_REQUEST_TYPE_UNDEFINED,
387                         null, null, -1, false, &errorMsg);
388 }
389
390 DataControlProviderManager*
391 _DataControlProviderManagerImpl::GetInstance(void)
392 {
393         static DataControlProviderManager* pDcMgr = null;
394
395         if (pDcMgr == null)
396         {
397                 pDcMgr = new (std::nothrow) DataControlProviderManager();
398                 SysTryReturn(NID_APP, pDcMgr, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory was insufficient.");
399         }
400
401         return pDcMgr;
402 }
403
404 // private
405 _DataControlProviderManagerImpl::_DataControlProviderManagerImpl(void)
406 {
407 }
408
409 _DataControlProviderManagerImpl::~_DataControlProviderManagerImpl(void)
410 {
411 }
412
413 } } // Tizen::App
414