2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file FIo_FileEventManager.cpp
19 * @brief This is the implementation file for _FileEventManager class.
22 #include <unique_ptr.h>
24 #include <sys/inotify.h>
27 #include <FBaseInteger.h>
28 #include <FBaseString.h>
29 #include <FBaseColAllElementsDeleter.h>
30 #include <FBaseColIMapEnumerator.h>
31 #include <FBaseSysLog.h>
33 #include <FIoFileEventManager.h>
34 #include <FIoIFileEventListener.h>
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"
43 using namespace Tizen::Base;
44 using namespace Tizen::Base::Runtime;
45 using namespace Tizen::Base::Collection;
47 namespace Tizen { namespace Io
50 _FileEventManagerImpl::_FileEventManagerImpl(void)
57 _FileEventManagerImpl::~_FileEventManagerImpl(void)
59 SysLog(NID_IO, "_FileEventManagerImpl: 0x%x", this);
61 if (__pWatchList != null)
63 _FileEventDispatcher* pDispatcher = _FileEventDispatcher::GetInstance();
64 IMapEnumerator* pMapEnum = __pWatchList->GetMapEnumeratorN();
65 while (pMapEnum->MoveNext() == E_SUCCESS)
67 Integer* pWd = dynamic_cast< Integer* >(pMapEnum->GetValue());
70 SysLog(NID_IO, "inotify fd: %d, watch description: %d", __inotifyFd, pWd->ToInt());
71 int res = inotify_rm_watch(__inotifyFd, pWd->ToInt());
72 SysTryLog(NID_IO, res == 0, "inotify_rm_watch() failed, errno: %d (%s)", errno, strerror(errno));
73 pDispatcher->RemoveFileEventInfo(*pWd);
84 _FileEventManagerImpl::Construct(IFileEventListener& listener)
86 unique_ptr< HashMap > pWatchList(new (std::nothrow) HashMap(SingleObjectDeleter));
87 SysTryReturnResult(NID_IO, pWatchList != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
88 pWatchList->Construct();
90 _FileEventDispatcher* pDispatcher = _FileEventDispatcher::GetInstance();
92 unique_ptr< _FileEvent > pEvent(new (std::nothrow) _FileEvent());
93 SysTryReturnResult(NID_IO, pEvent != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
94 result r = pEvent->Construct();
95 SysTryReturn(NID_IO, !IsFailed(r), E_IO, r, "[%s] The caller is a worker thread.", GetErrorMessage(r));
97 r = pEvent->AddListener(listener, true);
98 SysTryReturn(NID_IO, r == E_SUCCESS || r == E_OBJ_ALREADY_EXIST, E_IO, r,
99 "[%s] The caller is a worker thread.", GetErrorMessage(r));
101 __inotifyFd = pDispatcher->GetInotifyFd();
102 __pWatchList = pWatchList.release();
103 __pEvent = pEvent.release();
105 SysLog(NID_IO, "_FileEventManagerImpl: 0x%x, _Event: 0x%x", this, __pEvent);
110 _FileEventManagerImpl::AddPath(const String& path, unsigned long eventsToMonitor)
112 SysSecureLog(NID_IO, "Add watch path: %ls, _FileEventManagerImpl: 0x%x", path.GetPointer(), this);
113 result r = E_SUCCESS;
115 SysTryReturnResult(NID_IO, File::IsFileExist(path) == true, E_FILE_NOT_FOUND,
116 "The path (%ls) dose not exist.", path.GetPointer());
118 unique_ptr< char[] > pPath(_StringConverter::CopyToCharArrayN(path));
119 SysTryReturnResult(NID_IO, pPath != null, GetLastResult(), "Propagating to caller...");
121 int watchDescription = inotify_add_watch(__inotifyFd, pPath.get(), eventsToMonitor & ~IN_IGNORED);
122 if (watchDescription == -1)
128 SysLogException(NID_IO, E_IO, "Read access to the given file (%s) is not permitted.", pPath.get());
129 r = E_ILLEGAL_ACCESS;
132 SysLogException(NID_IO, E_IO, "The path (%s) points outside of the process's accessible address space.", pPath.get());
133 r = E_ILLEGAL_ACCESS;
136 SysLogException(NID_IO, E_IO, "The given file descriptor is not valid.");
139 SysLogException(NID_IO, E_INVALID_ARG, "The given event mask contains no valid events; or fd is not an inotify file descriptor.");
143 SysLogException(NID_IO, E_IO, "Insufficient kernel memory was available.");
146 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");
155 Integer* pWatchDescription = new (std::nothrow) Integer(watchDescription);
156 _FileEventInfo* pFileEventInfo = new (std::nothrow) _FileEventInfo();
157 String* pWatchPath = new (std::nothrow) String(path);
158 Integer* pWd = new (std::nothrow) Integer(watchDescription);
159 SysTryCatch(NID_IO, pWatchDescription != null && pFileEventInfo != null && pWatchPath != null && pWd != null,
160 r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "The memory is insufficient.");
162 pFileEventInfo->pFileEventManagerImpl = this;
163 pFileEventInfo->path = path;
165 r = _FileEventDispatcher::GetInstance()->AddFileEventInfo(pWatchDescription, pFileEventInfo);
166 SysTryCatch(NID_IO, r == E_SUCCESS || r == E_OBJ_ALREADY_EXIST, r = E_IO, r,
167 "[%s] Failed to add file event info.", GetErrorMessage(r));
168 if (r == E_OBJ_ALREADY_EXIST)
170 SysLog(NID_IO, "FileEventInfo already exists.");
171 delete pWatchDescription;
172 delete pFileEventInfo;
178 SysLog(NID_IO, "Add to watch list");
179 __pWatchList->Add(pWatchPath, pWd);
185 delete pWatchDescription;
186 delete pFileEventInfo;
194 _FileEventManagerImpl::RemovePath(const String& path)
196 SysSecureLog(NID_IO, "Remove watch path (%ls), _FileEventManagerImpl: 0x%x", path.GetPointer(), this);
198 Integer* pWd = dynamic_cast< Integer* >(__pWatchList->GetValue(path));
199 SysTryReturnResult(NID_IO, pWd != null, E_IO, "The path (%ls) is not registered.", path.GetPointer());
201 SysTryReturnResult(NID_IO, inotify_rm_watch(__inotifyFd, pWd->ToInt()) == 0,
202 E_IO, "The path (%ls) is not registered.", path.GetPointer());
204 _FileEventDispatcher::GetInstance()->RemoveFileEventInfo(*pWd);
205 __pWatchList->Remove(path);
210 _FileEventManagerImpl*
211 _FileEventManagerImpl::GetInstance(FileEventManager& fileEventManager)
213 return fileEventManager.__pFileEventManagerImpl;
216 const _FileEventManagerImpl*
217 _FileEventManagerImpl::GetInstance(const FileEventManager& fileEventManager)
219 return fileEventManager.__pFileEventManagerImpl;