Fix setting framework
[framework/osp/common-service.git] / src / system / FSys_RuntimeInfoStub.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         FSys_RuntimeInfoStub.cpp
20  * @brief       This is the implementation for the _RuntimeInfoStub class.
21  */
22 #include <pthread.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <stdio.h>
26
27 #include <FBaseSysLog.h>
28 #include <FBase_StringConverter.h>
29 #include <FIo_IpcServer.h>
30 #include <FIo_AppServiceIpcMessages.h>
31 #include <FSystem.h>
32
33 #include "FSys_RuntimeInfo.h"
34 #include "FSys_RuntimeInfoStub.h"
35
36 using namespace Tizen::Base;
37 using namespace Tizen::Base::Collection;
38 using namespace Tizen::Io;
39 using namespace Tizen::System;
40 using namespace Tizen::App;
41
42 namespace {
43         static const wchar_t* RUNTIME_INFO_STUB_MUTEX_ID = L"osp.sys.ipcserver.runtimeinfo";
44         static const int _RUNTIME_GET_PARAM_TYPE = 1;
45         static const wchar_t* _RUNTIME_SERVICE_ID = L"osp.sys.ipcserver.runtimeinfo";
46         static const wchar_t* _RUNTIME_GET_SIZE = L"osp.system.command.runtime.get.size";
47         static const wchar_t* _RUNTIME_RESULT_SUCCESS = L"osp.system.result.success";
48         static const wchar_t* _RUNTIME_RESULT_SYSTEM = L"osp.system.result.system";
49 }
50
51 _RuntimeInfoStub* _RuntimeInfoStub::__pRuntimeInfoStub = null;
52
53 static pthread_mutex_t send_msg_lock;
54 class _DirectorySizeObject
55 {
56 public:
57         _DirectorySizeObject()
58                 : path(null)
59                 , pid(0)
60                 , msg_id(0)
61         {
62         }
63         ~_DirectorySizeObject()
64         {
65                 if(path != null)
66                 {
67                         delete [] path;
68                 }
69         }
70
71         char* path;
72         int pid;
73         int msg_id;
74 };
75
76 _RuntimeInfoStub::_RuntimeInfoStub(void)
77         : __pIpcServer(null)
78         , __pIpcEventForAsync(null)
79 {
80         result r = E_SUCCESS;
81         r = __Mutex.Create(RUNTIME_INFO_STUB_MUTEX_ID);
82         SysTryReturn(NID_SYS, r == E_SUCCESS, , r, "It is failed to create mutex. [%s] Propaged.", GetErrorMessage(r));
83
84         if(pthread_mutex_init(&send_msg_lock, null))
85         {
86                 SysLogException(NID_SYS, E_SYSTEM, "It is failed to init mutex.");
87         }
88 }
89
90 _RuntimeInfoStub::~_RuntimeInfoStub(void)
91 {
92         if (__pIpcServer)
93         {
94                 __pIpcServer->Stop();
95         }
96
97         result  r = __Mutex.Release();
98         SysTryReturn(NID_SYS, r == E_SUCCESS, , r, "It is failed to release mutex. [%s] Propaged.", GetErrorMessage(r));
99
100         if(pthread_mutex_destroy(&send_msg_lock))
101         {
102                 SysLogException(NID_SYS, E_SYSTEM, "It is failed to term mutex.");
103         }
104 }
105
106 _RuntimeInfoStub*
107 _RuntimeInfoStub::GetInstance(void)
108 {
109         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
110
111         if (__pRuntimeInfoStub == null)
112         {
113                 pthread_once(&onceBlock, InitSingleton);
114         }
115         return __pRuntimeInfoStub;
116 }
117
118 void
119 _RuntimeInfoStub::InitSingleton(void)
120 {
121         std::unique_ptr< _RuntimeInfoStub > pRuntimeInfoStub(new (std::nothrow) _RuntimeInfoStub());
122         SysTryReturn(NID_SYS, pRuntimeInfoStub, , E_OUT_OF_MEMORY, "It is not enough memory.");
123
124         result r = pRuntimeInfoStub->Construct();
125         SysTryReturn(NID_SYS, !IsFailed(r), , r, "[%s] It is failed to get RuntimeInfoCommunicationStub.", GetErrorMessage(r));
126         __pRuntimeInfoStub = pRuntimeInfoStub.release();
127         atexit(DestroySingleton);
128 }
129
130 void
131 _RuntimeInfoStub::DestroySingleton(void)
132 {
133         delete __pRuntimeInfoStub;
134 }
135
136 result
137 _RuntimeInfoStub::Construct(void)
138 {
139         std::unique_ptr<_IpcServer> pIpcServer(new (std::nothrow) _IpcServer());
140         SysTryReturnResult(NID_SYS, pIpcServer, E_OUT_OF_MEMORY, "Memory is insufficient.");
141
142         result r = pIpcServer->Construct(String(_RUNTIME_SERVICE_ID), *this, true);
143         SysTryReturnResult(NID_SYS, r == E_SUCCESS, r, "It is failed to construct.");
144
145         r = pIpcServer->Start();
146         SysTryReturnResult(NID_SYS, r == E_SUCCESS, r, "It is failed to start.");
147
148         __pIpcServer = move(pIpcServer);
149         return E_SUCCESS;
150 }
151
152 void
153 _RuntimeInfoStub::OnIpcRequestReceived(_IpcServer& server, const IPC::Message& message)
154 {
155         __currentPid = server.GetClientId();
156         IPC_BEGIN_MESSAGE_MAP(_RuntimeInfoStub, message)
157                 IPC_MESSAGE_HANDLER_EX(IoService_Request, &server, OnRequestOccured)
158         IPC_END_MESSAGE_MAP_EX()
159 }
160
161 bool
162 _RuntimeInfoStub::OnRequestOccured(const ArrayList& request, ArrayList* response)
163 {
164         bool isSuccess = false;
165         result r = E_SUCCESS;
166
167         __serviceId = _RUNTIME_SERVICE_ID;
168         __command = *((String*)request.GetAt(_RUNTIME_GET_PARAM_TYPE));
169         __result = L"";
170
171         if(__command == _RUNTIME_GET_SIZE)
172         {
173                 int mid = 0;
174                 String* path = (String*)request.GetAt(_RUNTIME_GET_PARAM_TYPE+1);
175                 String* messageId = (String*)request.GetAt(_RUNTIME_GET_PARAM_TYPE+2);
176                 SysTryCatch(NID_SYS, path != null, r = E_SYSTEM, E_SYSTEM, "There is no path information.");
177
178                 std::unique_ptr< char > directoryPath(_StringConverter::CopyToCharArrayN(*path));
179                 Integer::Parse(*messageId, mid);
180                 _DirectorySizeObject* dso = new (std::nothrow) _DirectorySizeObject();
181                 dso->pid = __currentPid;
182                 dso->path = directoryPath.release();
183                 dso->msg_id = mid;
184
185                 pthread_t p_thread;
186                 int thr_id = pthread_create(&p_thread, null, _RuntimeInfoStub::GetDirectorySizeAsync, dso);
187                 if(thr_id < 0)
188                 {
189                         __result = _RUNTIME_RESULT_SYSTEM;
190                 }
191                 else
192                 {
193                         pthread_detach(p_thread);
194                         __result = _RUNTIME_RESULT_SUCCESS;
195                 }
196         }
197         else
198         {
199                 __result =  _RUNTIME_RESULT_SYSTEM;
200         }
201
202         isSuccess = true;
203 CATCH:
204         response->Add(__serviceId);
205         response->Add(__command);
206         if (isSuccess == true)
207         {
208                 response->Add(__result);
209         }
210
211         ArrayList* temp = const_cast<ArrayList*>(&request);
212         temp->RemoveAll(true);
213         return isSuccess;
214 }
215
216 void*
217 _RuntimeInfoStub::GetDirectorySizeAsync(void* data)
218 {
219         result r= E_SUCCESS;
220         long long size = 0;
221
222         _DirectorySizeObject* dso = (_DirectorySizeObject*) data;
223         SysTryCatch(NID_SYS, dso != null, r = E_SYSTEM, r, "There is no _DirectorySizeObject.");
224         size = _RuntimeInfo::GetDirectorySize(dso->path);
225
226 CATCH:
227         _RuntimeInfoStub::SendResponse(dso->pid, dso->msg_id, size, r);
228         delete dso;
229         return null;
230 }
231
232 void
233 _RuntimeInfoStub::SendResponse(int pid, int msg_id, long long size, result rcode)
234 {
235         result r = E_SUCCESS;
236         pthread_mutex_lock(&send_msg_lock);
237
238         ArrayList* data = null;
239         String* pValue = null;
240         String* pMessageId = null;
241
242         SysLog(NID_SYS, "It sends asynchronous result to pid [%d].", pid);
243
244         data = new (std::nothrow) ArrayList(SingleObjectDeleter);
245         data->Construct();
246
247         pMessageId = new (std::nothrow) String();
248         pMessageId->Append(msg_id);
249
250         data->Add(new (std::nothrow) String(_RUNTIME_SERVICE_ID));
251         data->Add(new (std::nothrow) String(_RUNTIME_GET_SIZE));
252         data->Add(pMessageId);
253
254         pValue = new (std::nothrow) String();
255         pValue->Append(size);
256         data->Add(pValue);
257
258         if(rcode == E_SUCCESS)
259         {
260                 data->Add(new (std::nothrow) String(_RUNTIME_RESULT_SUCCESS));
261         }
262         else
263         {
264                 data->Add(new (std::nothrow) String(_RUNTIME_RESULT_SYSTEM));
265         }
266
267         _RuntimeInfoStub* pRuntimeInfoStub = null;
268         pRuntimeInfoStub =  _RuntimeInfoStub::GetInstance();
269         SysTryReturn(NID_SYS, pRuntimeInfoStub, , E_SYSTEM, "RuntimeInfoStub is not created.");
270
271         pRuntimeInfoStub->SendDataAsync(pid, data);
272 CATCH:
273         pthread_mutex_unlock(&send_msg_lock);
274
275 }
276
277 result
278 _RuntimeInfoStub::SendDataAsync(const int pid, Tizen::Base::Collection::ArrayList* data)
279 {
280         __Mutex.Acquire();
281         result r = E_SUCCESS;
282
283         SysTryCatch(NID_SYS, __pIpcServer != null, r = E_SYSTEM, E_SYSTEM, "IPC server is not ready.");
284         SysTryCatch(NID_SYS, data != null, r = E_SYSTEM, E_SYSTEM, "There is no data.");
285
286         if(__pIpcEventForAsync == null)
287         {
288                 __pIpcEventForAsync.reset(new (std::nothrow) _SystemServiceIpcEventForAsync(__pIpcServer.get()));
289                 SysTryCatch(NID_SYS, __pIpcEventForAsync != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "It is not enough memory.");
290                 __pIpcEventForAsync->Construct(1048576, Tizen::Base::Runtime::THREAD_PRIORITY_MID);
291                 __pIpcEventForAsync->Start();
292         }
293
294         r = __pIpcEventForAsync->SendUserEvent((RequestId)pid, (IList*)data);
295         SysTryCatch(NID_SYS, r == E_SUCCESS, r = E_SYSTEM, E_SYSTEM, "Message is failed to add on event thread.");
296
297 CATCH:
298         if(r != E_SUCCESS)
299         {
300                 delete data;
301         }
302         __Mutex.Release();
303         return r;
304 }