Merge "update media-capability for emulator" into tizen_2.1
[platform/framework/native/appfw.git] / src / io / FIo_FileEventManagerImpl.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file        FIo_FileEventManager.cpp
19  * @brief       This is the implementation file for _FileEventManager class.
20  */
21
22 #include <unique_ptr.h>
23 #include <unistd.h>
24 #include <sys/inotify.h>
25 #include <errno.h>
26
27 #include <FBaseInteger.h>
28 #include <FBaseString.h>
29 #include <FBaseColAllElementsDeleter.h>
30 #include <FBaseColIMapEnumerator.h>
31 #include <FBaseSysLog.h>
32 #include <FIoFile.h>
33 #include <FIoFileEventManager.h>
34 #include <FIoIFileEventListener.h>
35
36 #include <FBase_StringConverter.h>
37 #include <FBase_NativeError.h>
38 #include "FIo_FileEventManagerImpl.h"
39 #include "FIo_FileEventDispatcher.h"
40 #include "FIo_FileEvent.h"
41
42 using namespace std;
43 using namespace Tizen::Base;
44 using namespace Tizen::Base::Runtime;
45 using namespace Tizen::Base::Collection;
46
47 namespace Tizen { namespace Io
48 {
49
50 _FileEventManagerImpl::_FileEventManagerImpl(void)
51         : __pWatchList(null)
52         , __pEvent(null)
53         , __inotifyFd(-1)
54 {
55 }
56
57 _FileEventManagerImpl::~_FileEventManagerImpl(void)
58 {
59         SysLog(NID_IO, "_FileEventManagerImpl: 0x%x", this);
60         _FileEventDispatcher* pDispatcher = _FileEventDispatcher::GetInstance();
61
62         IMapEnumerator* pMapEnum = __pWatchList->GetMapEnumeratorN();
63         while (pMapEnum->MoveNext() == E_SUCCESS)
64         {
65                 Integer* pWd = dynamic_cast< Integer* >(pMapEnum->GetValue());
66                 if (pWd != null)
67                 {
68                         SysLog(NID_IO, "inotify fd: %d, watch description: %d", __inotifyFd, pWd->ToInt());
69                         int res = inotify_rm_watch(__inotifyFd, pWd->ToInt());
70                         SysTryLog(NID_IO, res == 0, "inotify_rm_watch() failed, errno: %d (%s)", errno, strerror(errno));
71                         pDispatcher->RemoveFileEventInfo(*pWd);
72                 }
73         }
74
75         delete __pWatchList;
76         delete __pEvent;
77 }
78
79 result
80 _FileEventManagerImpl::Construct(IFileEventListener& listener)
81 {
82         unique_ptr< HashMap > pWatchList(new (std::nothrow) HashMap(SingleObjectDeleter));
83         SysTryReturnResult(NID_IO, pWatchList != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
84         pWatchList->Construct();
85
86         unique_ptr< _FileEvent > pEvent(new (std::nothrow) _FileEvent());
87         SysTryReturnResult(NID_IO, pEvent != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
88
89         result r = pEvent->AddListener(listener, true);
90         SysTryReturn(NID_IO, r == E_SUCCESS || r == E_OBJ_ALREADY_EXIST, E_IO, r,
91                         "[%s] The caller thread is a worker thread.", GetErrorMessage(r));
92
93         _FileEventDispatcher* pDispatcher = _FileEventDispatcher::GetInstance();
94         __inotifyFd = pDispatcher->GetInotifyFd();
95         __pWatchList = pWatchList.release();
96         __pEvent = pEvent.release();
97
98         SysLog(NID_IO, "_FileEventManagerImpl: 0x%x, _Event: 0x%x", this, __pEvent);
99         return E_SUCCESS;
100 }
101
102 result
103 _FileEventManagerImpl::AddPath(const String& path, unsigned long eventsToMonitor)
104 {
105         SysSecureLog(NID_IO, "Add watch path: %ls, _FileEventManagerImpl: 0x%x", path.GetPointer(), this);
106         result r = E_SUCCESS;
107
108         SysTryReturnResult(NID_IO, File::IsFileExist(path) == true, E_FILE_NOT_FOUND,
109                         "The path (%ls) dose not exist.", path.GetPointer());
110
111         unique_ptr< char[] > pPath(_StringConverter::CopyToCharArrayN(path));
112         SysTryReturnResult(NID_IO, pPath != null, GetLastResult(), "Propagating to caller...");
113
114         int watchDescription = inotify_add_watch(__inotifyFd, pPath.get(), eventsToMonitor & ~IN_IGNORED);
115         if (watchDescription == -1)
116         {
117                 r = E_IO;
118                 switch (errno)
119                 {
120                 case EACCES:
121                         SysLogException(NID_IO, E_IO, "Read access to the given file (%s) is not permitted.", pPath.get());
122                         r = E_ILLEGAL_ACCESS;
123                         break;
124                 case EFAULT:
125                         SysLogException(NID_IO, E_IO, "The path (%s) points outside of the process's accessible address space.", pPath.get());
126                         r = E_ILLEGAL_ACCESS;
127                         break;
128                 case EBADF:
129                         SysLogException(NID_IO, E_IO, "The given file descriptor is not valid.");
130                         break;
131                 case EINVAL:
132                         SysLogException(NID_IO, E_INVALID_ARG, "The given event mask contains no valid events; or fd is not an inotify file descriptor.");
133                         r = E_INVALID_ARG;
134                         break;
135                 case ENOMEM:
136                         SysLogException(NID_IO, E_IO, "Insufficient kernel memory was available.");
137                         break;
138                 case ENOSPC:
139                         SysLogException(NID_IO, E_IO, "The user limit on the total number of inotify watches was reached or the kernel failed to allocate a needed resource");
140                         break;
141                 default:
142                         break;
143                 }
144
145                 return r;
146         }
147
148         Integer* pWatchDescription = new (std::nothrow) Integer(watchDescription);
149         _FileEventInfo* pFileEventInfo = new (std::nothrow) _FileEventInfo();
150         String* pWatchPath = new (std::nothrow) String(path);
151         Integer* pWd = new (std::nothrow) Integer(watchDescription);
152         SysTryCatch(NID_IO, pWatchDescription != null && pFileEventInfo != null && pWatchPath != null && pWd != null,
153                         r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "The memory is insufficient.");
154
155         pFileEventInfo->pFileEventManagerImpl = this;
156         pFileEventInfo->path = path;
157
158         r = _FileEventDispatcher::GetInstance()->AddFileEventInfo(pWatchDescription, pFileEventInfo);
159         SysTryCatch(NID_IO, r == E_SUCCESS || r == E_OBJ_ALREADY_EXIST, r = E_IO, r,
160                         "[%s] Failed to add file event info.", GetErrorMessage(r));
161         if (r == E_OBJ_ALREADY_EXIST)
162         {
163                 SysLog(NID_IO, "FileEventInfo already exists.");
164                 delete pWatchDescription;
165                 delete pFileEventInfo;
166                 delete pWatchPath;
167                 delete pWd;
168         }
169         else
170         {
171                 SysLog(NID_IO, "Add to watch list");
172                 __pWatchList->Add(pWatchPath, pWd);
173         }
174
175         return E_SUCCESS;
176
177 CATCH:
178         delete pWatchDescription;
179         delete pFileEventInfo;
180         delete pWatchPath;
181         delete pWd;
182
183         return r;
184 }
185
186 result
187 _FileEventManagerImpl::RemovePath(const String& path)
188 {
189         SysSecureLog(NID_IO, "Remove watch path (%ls), _FileEventManagerImpl: 0x%x", path.GetPointer(), this);
190
191         Integer* pWd = dynamic_cast< Integer* >(__pWatchList->GetValue(path));
192         SysTryReturnResult(NID_IO, pWd != null, E_IO, "The path (%ls) is not registered.", path.GetPointer());
193
194         SysTryReturnResult(NID_IO, inotify_rm_watch(__inotifyFd, pWd->ToInt()) == 0,
195                         E_IO, "The path (%ls) is not registered.", path.GetPointer());
196
197         _FileEventDispatcher::GetInstance()->RemoveFileEventInfo(*pWd);
198         __pWatchList->Remove(path);
199
200         return E_SUCCESS;
201 }
202
203 _FileEventManagerImpl*
204 _FileEventManagerImpl::GetInstance(FileEventManager& fileEventManager)
205 {
206         return fileEventManager.__pFileEventManagerImpl;
207 }
208
209 const _FileEventManagerImpl*
210 _FileEventManagerImpl::GetInstance(const FileEventManager& fileEventManager)
211 {
212         return fileEventManager.__pFileEventManagerImpl;
213 }
214
215 }} // Tizen::Io
216