From: Hyunbin Lee Date: Thu, 9 May 2013 13:53:56 +0000 (+0900) Subject: Apply singleton pattern to reduce the number of used inotify instances. X-Git-Tag: accepted/tizen/20130912.081851^2~311 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1e23393fd8500526cc1977c0e2d9528495aada64;p=platform%2Fframework%2Fnative%2Fappfw.git Apply singleton pattern to reduce the number of used inotify instances. Change-Id: I55b88c38b1ac3018182294850be15cfaf9c0c6ed Signed-off-by: Hyunbin Lee --- diff --git a/src/io/CMakeLists.txt b/src/io/CMakeLists.txt index 3485c5d..098e03c 100644 --- a/src/io/CMakeLists.txt +++ b/src/io/CMakeLists.txt @@ -38,6 +38,8 @@ SET (${this_target}_SOURCE_FILES FIo_FileAttributesImpl.cpp FIoFileEventManager.cpp FIo_FileEventManagerImpl.cpp + FIo_FileEventDispatcher.cpp + FIo_FileEvent.cpp FIoRegistry.cpp FIo_RegistryImpl.cpp FIo_RegistryCore.cpp diff --git a/src/io/FIo_FileEvent.cpp b/src/io/FIo_FileEvent.cpp new file mode 100644 index 0000000..607ce1c --- /dev/null +++ b/src/io/FIo_FileEvent.cpp @@ -0,0 +1,52 @@ +// +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FIo_FileEvent.cpp + * @brief This is the implementation file for _FileEvent class. + */ + +//#include +#include +#include "FIo_FileEvent.h" + +using namespace Tizen::Base::Runtime; + +namespace Tizen { namespace Io +{ + +_FileEvent::_FileEvent(void) +{ + _Event::Initialize(); +} + +void +_FileEvent::FireImpl(IEventListener& listener, const IEventArg& arg) +{ + IFileEventListener* pListener = dynamic_cast< IFileEventListener* >(&listener); + if (pListener != null) + { + const _FileEventArg* pArg = dynamic_cast(&arg); + if (pArg != null) + { + //SysLog(NID_IO, "event: 0x%x, path: %ls, eventId: %d", pArg->__event, pArg->__path.GetPointer(), pArg->__eventId); + pListener->OnFileEventOccured(pArg->__event, pArg->__path, pArg->__eventId); + } + } +} + +}} // Tizen::Io + diff --git a/src/io/FIo_FileEvent.h b/src/io/FIo_FileEvent.h new file mode 100644 index 0000000..0a6e8a0 --- /dev/null +++ b/src/io/FIo_FileEvent.h @@ -0,0 +1,65 @@ +// +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FIo_FileEvent.h + * @brief This is the header file for the _FileEvent class. + * + * This header file contains the declarations of the _FileEvent class. + */ + +#ifndef _FIO_INTERNAL_FILE_EVENT_H_ +#define _FIO_INTERNAL_FILE_EVENT_H_ + +#include +#include +#include + +namespace Tizen { namespace Io +{ + +class _FileEventArg + : public Tizen::Base::Runtime::IEventArg +{ + +public: + _FileEventArg(unsigned long event, Tizen::Base::String path, unsigned int eventId) + : __event(event) + , __path(path) + , __eventId(eventId) + { + } + unsigned long __event; + Tizen::Base::String __path; + unsigned int __eventId; +}; // _FileEventArg + +class _FileEvent + : public Tizen::Base::Runtime::_Event +{ + +public: + _FileEvent(void); + +protected: + virtual void FireImpl(Tizen::Base::Runtime::IEventListener& listener, const Tizen::Base::Runtime::IEventArg& arg); + +}; // _FileEvent + +}} // Tizen::Io + +#endif // _FIO_INTERNAL_FILE_EVENT_H_ + diff --git a/src/io/FIo_FileEventDispatcher.cpp b/src/io/FIo_FileEventDispatcher.cpp new file mode 100644 index 0000000..3987029 --- /dev/null +++ b/src/io/FIo_FileEventDispatcher.cpp @@ -0,0 +1,304 @@ +// +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FIo_FileEventDispatcher.cpp + * @brief This is the implementation file for _FileEventDispatcher class. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "FIo_FileEventManagerImpl.h" +#include "FIo_FileEventDispatcher.h" +#include "FIo_FileEvent.h" + +#define INOTIFY_BUFFER_LEN (1024*(sizeof(struct inotify_event) + 16)) + +using namespace std; +using namespace Tizen::Base; +using namespace Tizen::Base::Collection; +using namespace Tizen::Base::Runtime; + +namespace Tizen { namespace Io +{ + +_FileEventDispatcher* _FileEventDispatcher::__pFileEventDispatcherInstance = null; + +_FileEventDispatcher::_FileEventDispatcher(void) + : __pWatchList(null) + , __inotifyFd(-1) + , __pGSource(null) + , __pGIOChannel(null) +{ +} + +result +_FileEventDispatcher::Construct(void) +{ + unique_ptr< HashMap > pWatchList(new (std::nothrow) HashMap(SingleObjectDeleter)); + SysTryReturnResult(NID_IO, pWatchList != null, E_OUT_OF_MEMORY, "The memory is insufficient."); + + result r = pWatchList->Construct(); + SysTryReturnResult(NID_IO, !IsFailed(r), r, "Propagating to caller..."); + + __inotifyFd = inotify_init(); + if (__inotifyFd == -1) + { + switch (errno) + { + case EMFILE: + SysLogException(NID_IO, E_MAX_EXCEEDED, + "The total number of inotify instances has exceeded the maximum limit."); + r = E_MAX_EXCEEDED; + break; + case ENFILE: + SysLogException(NID_IO, E_MAX_EXCEEDED, + "The total number of file descriptors has exceeded the maximum limit."); + r = E_MAX_EXCEEDED; + break; + case ENOMEM: + SysLogException(NID_IO, E_OUT_OF_MEMORY, "The memory is insufficient."); + r = E_OUT_OF_MEMORY; + break; + default: + SysLogException(NID_IO, E_SYSTEM, "The method cannot proceed due to a severe system error."); + r = E_SYSTEM; + break; + } + + SysLog(NID_IO, "errno: %d (%s)", errno, strerror(errno)); + return r; + } + + GMainContext* pGContext = g_main_context_get_thread_default(); //get own gmain context except default thread + if (pGContext == null) + { + pGContext = g_main_context_default(); //get gmain context from me (default) + SysTryReturnResult(NID_IO, pGContext != null, E_IO, "Failed to get gmain context."); + } + + __pGIOChannel = g_io_channel_unix_new(__inotifyFd); //fd wrapping + SysTryCatch(NID_IO, __pGIOChannel != null, r = E_IO, E_IO, "[E_IO] Failed to create gio channel."); + + __pGSource = g_io_create_watch(__pGIOChannel, (GIOCondition)(G_IO_IN | G_IO_ERR | G_IO_NVAL | G_IO_HUP)); + SysTryCatch(NID_IO, __pGSource != null, r = E_IO, E_IO, "[E_IO] Failed to create gsource."); + + g_source_set_callback(__pGSource, (GSourceFunc)OnFileEventOccurred, this, null); + g_source_attach(__pGSource, pGContext); + + __pWatchList = pWatchList.release(); + + SysLog(NID_IO, "inotify fd: %d, channel: 0x%x", __inotifyFd, __pGIOChannel); + return E_SUCCESS; + +CATCH: + if (__inotifyFd != -1) + { + close(__inotifyFd); + } + + if (__pGSource != null) + { + g_source_destroy(__pGSource); + g_source_unref(__pGSource); + __pGSource = null; + } + + if (__pGIOChannel != null) + { + g_io_channel_unref(__pGIOChannel); + __pGIOChannel = null; + } + + return r; +} + +_FileEventDispatcher::~_FileEventDispatcher(void) +{ + if (__inotifyFd != -1) + { + close(__inotifyFd); + } + + if (__pGSource != null) + { + g_source_destroy(__pGSource); + g_source_unref(__pGSource); + } + + if (__pGIOChannel != null) + { + g_io_channel_unref(__pGIOChannel); + } + + delete __pWatchList; +} + +void +_FileEventDispatcher::InitSingleton(void) +{ + _FileEventDispatcher* pInst = new (std::nothrow) _FileEventDispatcher(); + SysTryReturnVoidResult(NID_IO, pInst != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient."); + + result r = pInst->Construct(); + SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r)); + + __pFileEventDispatcherInstance = pInst; + + std::atexit(DestroySingleton); + return; + +CATCH: + delete pInst; +} + +void +_FileEventDispatcher::DestroySingleton(void) +{ + delete __pFileEventDispatcherInstance; +} + +_FileEventDispatcher* +_FileEventDispatcher::GetInstance(void) +{ + static pthread_once_t onceBlock = PTHREAD_ONCE_INIT; + + if (__pFileEventDispatcherInstance == null) + { + ClearLastResult(); + pthread_once(&onceBlock, InitSingleton); + result r = GetLastResult(); + if (IsFailed(r)) + { + onceBlock = PTHREAD_ONCE_INIT; + SysPropagate(NID_IO, r); + } + } + + return __pFileEventDispatcherInstance; +} + +result +_FileEventDispatcher::SendEvent(void) +{ + SysTryReturnResult(NID_IO, __inotifyFd != -1, E_IO, "inotify fd is invalid."); + SysLog(NID_IO, "inotify fd: %d", __inotifyFd); + + char buffer[INOTIFY_BUFFER_LEN + 1] = { 0, }; + ssize_t length = read(__inotifyFd, buffer, INOTIFY_BUFFER_LEN); + SysTryReturnResult(NID_IO, length < (long)INOTIFY_BUFFER_LEN, E_IO, "Read buffer has failed."); + + unsigned long iter = 0; + while (iter < static_cast< unsigned long >(length)) + { + struct inotify_event* pEvent = (struct inotify_event*)&buffer[iter]; + SysTryReturnResult(NID_IO, pEvent != null, E_IO, "inotify event info not found."); + + Integer wd(pEvent->wd); + _FileEventInfo* pFileEventInfo = GetFileEventInfo(wd); + SysLog(NID_IO, "wd: %d, _FileEventInfo: 0x%x, event mask: 0x%x", pEvent->wd, pFileEventInfo, pEvent->mask); + if (pFileEventInfo == null) + { + SysLog(NID_IO, "There is no watch path."); + } + else + { + unsigned long event = (unsigned long)pEvent->mask; + unsigned int eventId = pEvent->cookie; + + String path; + if (pEvent->len) + { + // TODO: Use full path in Tizen 3.0 + path.Append(pEvent->name); + } + else + { + path.Append(pFileEventInfo->path); + } + // TODO: Resolve path + SysLog(NID_IO, "watch path: %ls", path.GetPointer()); + + _FileEventArg* pEventArg= new (std::nothrow) _FileEventArg(event, path, eventId); + if (pEventArg != null) + { + _Event* pFileEvent = pFileEventInfo->pFileEventManagerImpl->GetEvent(); + if (pFileEvent != null) + { + SysLog(NID_IO, "Fire async event, _FileEventManagerImpl: 0x%x, _Event: 0x%x, event mask: 0x%x, eventId: %d", + pFileEventInfo->pFileEventManagerImpl, pFileEvent, event, eventId); + pFileEvent->FireAsync(*pEventArg); + } + } + } + + iter += sizeof(struct inotify_event) + pEvent->len; + } + + return E_SUCCESS; +} + +gboolean +_FileEventDispatcher::OnFileEventOccurred(GIOChannel* source, GIOCondition condition, gpointer data) +{ + SysLog(NID_IO, "channel: 0x%x, condition: %d", source, (int)condition); + + if (condition & G_IO_IN) + { + _FileEventDispatcher* pDispatcher = static_cast< _FileEventDispatcher* >(data); + if (pDispatcher != null) + { + pDispatcher->SendEvent(); + } + } + + return true; +} + +result +_FileEventDispatcher::AddFileEventInfo(Integer* pWatchDescription, _FileEventInfo* pFileEventInfo) +{ + SysLog(NID_IO, "Add event info, wd: %d, _FileEventInfo: 0x%x, _FileEventManagerImpl: 0x%x", + pWatchDescription->ToInt(), pFileEventInfo, pFileEventInfo->pFileEventManagerImpl); + return __pWatchList->Add(pWatchDescription, pFileEventInfo); +} + +_FileEventInfo* +_FileEventDispatcher::GetFileEventInfo(Integer& watchDescription) +{ + SysLog(NID_IO, "Get event info, wd: %d", watchDescription.ToInt()); + return dynamic_cast< _FileEventInfo* >(__pWatchList->GetValue(watchDescription)); +} + +void +_FileEventDispatcher::RemoveFileEventInfo(Integer& watchDescription) +{ + SysLog(NID_IO, "Remove event info, wd: %d", watchDescription.ToInt()); + __pWatchList->Remove(watchDescription); +} + +}} // Tizen::Io + diff --git a/src/io/FIo_FileEventDispatcher.h b/src/io/FIo_FileEventDispatcher.h new file mode 100644 index 0000000..00983b0 --- /dev/null +++ b/src/io/FIo_FileEventDispatcher.h @@ -0,0 +1,102 @@ +// +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FIo_FileEventDispatcher.h + * @brief This is the header file for the _FileEventDispatcher class. + * + * This header file contains the declarations of the _FileEventDispatcher class. + */ + +#ifndef _FIO_INTERNAL_FILE_EVENT_DISPATCHER_H_ +#define _FIO_INTERNAL_FILE_EVENT_DISPATCHER_H_ + +#include + +#include +#include +#include + +namespace Tizen { namespace Io +{ + +class _FileEventManagerImpl; + +class _FileEventInfo + : public Tizen::Base::Object +{ +public: + _FileEventInfo(void) + : pFileEventManagerImpl(null) + { + } + virtual ~_FileEventInfo(void) + { + } + _FileEventManagerImpl* pFileEventManagerImpl; + Tizen::Base::String path; +}; // _FileEventInfo + +class _FileEventDispatcher + : public Tizen::Base::Object +{ + +public: + result SendEvent(void); + + int GetInotifyFd(void) + { + return __inotifyFd; + } + + result AddFileEventInfo(Tizen::Base::Integer* pWatchDescription, _FileEventInfo* pFileEventInfo); + + _FileEventInfo* GetFileEventInfo(Tizen::Base::Integer& watchDescription); + + void RemoveFileEventInfo(Tizen::Base::Integer& watchDescription); + + static _FileEventDispatcher* GetInstance(void); + +private: + _FileEventDispatcher(void); + + result Construct(void); + + virtual ~_FileEventDispatcher(void); + + _FileEventDispatcher(const _FileEventDispatcher& rhs); + + _FileEventDispatcher& operator =(const _FileEventDispatcher& rhs); + + static void InitSingleton(void); + + static void DestroySingleton(void); + + static gboolean OnFileEventOccurred(GIOChannel* source, GIOCondition condition, gpointer data); + +private: + static _FileEventDispatcher* __pFileEventDispatcherInstance; + Tizen::Base::Collection::HashMap* __pWatchList; + int __inotifyFd; + GSource* __pGSource; + GIOChannel* __pGIOChannel; + +}; // _FileEventDispatcher + +}} // Tizen::Io + +#endif // _FIO_INTERNAL_FILE_EVENT_DISPATCHER_H_ + diff --git a/src/io/FIo_FileEventManagerImpl.cpp b/src/io/FIo_FileEventManagerImpl.cpp index 61da638..5fd8111 100644 --- a/src/io/FIo_FileEventManagerImpl.cpp +++ b/src/io/FIo_FileEventManagerImpl.cpp @@ -16,29 +16,28 @@ /** * @file FIo_FileEventManager.cpp - * @brief This is the implementation file for FileEventManager class. + * @brief This is the implementation file for _FileEventManager class. */ +#include #include #include #include -#include -#include #include #include -#include #include -#include +#include +#include #include -#include #include +#include #include #include -#include - -#define INOTIFY_BUFFER_LEN (1024*(sizeof(struct inotify_event) + 16)) +#include "FIo_FileEventManagerImpl.h" +#include "FIo_FileEventDispatcher.h" +#include "FIo_FileEvent.h" using namespace std; using namespace Tizen::Base; @@ -48,235 +47,82 @@ using namespace Tizen::Base::Collection; namespace Tizen { namespace Io { -class _FileEventArg - : public IEventArg -{ -public: - _FileEventArg(unsigned long event, String path, unsigned int eventId) - : __event(event) - , __path(path) - , __eventId(eventId) - { - } - unsigned long __event; - String __path; - unsigned int __eventId; -}; - -class _FileEvent - : public _Event -{ -public: - _FileEvent(void) - { - _Event::Initialize(); - } -protected: - virtual void FireImpl(IEventListener& listener, const IEventArg& arg) - { - IFileEventListener* pListener = dynamic_cast (&listener); - if (pListener != null) - { - const _FileEventArg* pArg = dynamic_cast(&arg); - if (pArg != null) - { - pListener->OnFileEventOccured(pArg->__event, pArg->__path, pArg->__eventId); - } - } - } -}; - _FileEventManagerImpl::_FileEventManagerImpl(void) - : __pMonitorFileList(null) + : __pWatchList(null) , __pEvent(null) , __inotifyFd(-1) - , __pGSource(null) - , __pGIOChannel(null) { } _FileEventManagerImpl::~_FileEventManagerImpl(void) { - if (__inotifyFd != -1) - { - close(__inotifyFd); - } - - if (__pGIOChannel != null) - { - g_io_channel_unref(__pGIOChannel); - } - - if (__pGSource != null) - { - g_source_destroy(__pGSource); - g_source_unref(__pGSource); - } + SysLog(NID_IO, "_FileEventManagerImpl: 0x%x", this); + _FileEventDispatcher* pDispatcher = _FileEventDispatcher::GetInstance(); - if (__pMonitorFileList != null) + IMapEnumerator* pMapEnum = __pWatchList->GetMapEnumeratorN(); + while (pMapEnum->MoveNext() == E_SUCCESS) { - __pMonitorFileList->RemoveAll(true); - delete __pMonitorFileList; - } - - delete __pEvent; -} - -gboolean -_FileEventManagerImpl::OnFileEventOccured(GIOChannel* source, GIOCondition condition, gpointer data) -{ - _FileEventManagerImpl* pFileEventManagerImpl = (_FileEventManagerImpl*)data; - - pFileEventManagerImpl->SendEvent(); - - return true; -} - -result -_FileEventManagerImpl::SendEvent(void) -{ - unsigned long iter = 0; - ssize_t length = 0; - char buffer[INOTIFY_BUFFER_LEN + 1] = {0,}; - - unsigned long event = 0; - String path; - unsigned int eventId = 0; - result r = E_IO; - - SysTryReturnResult(NID_IO, __inotifyFd != -1, E_IO, "Failed to inotify."); - - length = read(__inotifyFd, buffer, INOTIFY_BUFFER_LEN); - SysTryReturnResult(NID_IO, length < (long)INOTIFY_BUFFER_LEN, E_IO, "Read buffer has failed."); - - while (iter < static_cast (length)) - { - struct inotify_event* pEvent = (struct inotify_event*)&buffer[iter]; - SysTryReturnResult(NID_IO, pEvent != null, E_IO, "Event info not found."); - event = (unsigned long)pEvent->mask; - eventId = pEvent->cookie; - - if (pEvent->len) - { - path = pEvent->name; - } - else + Integer* pWd = dynamic_cast< Integer* >(pMapEnum->GetValue()); + if (pWd != null) { - path = GetRegisteredPath(pEvent->wd); + SysLog(NID_IO, "inotify fd: %d, watch description: %d", __inotifyFd, pWd->ToInt()); + int res = inotify_rm_watch(__inotifyFd, pWd->ToInt()); + SysTryLog(NID_IO, res == 0, "inotify_rm_watch() failed, errno: %d (%s)", errno, strerror(errno)); + pDispatcher->RemoveFileEventInfo(*pWd); } - - _FileEventArg* pEventArg= new (std::nothrow) _FileEventArg(event, path, eventId); - if(pEventArg != null) - { - SysLog(NID_IO, "_FileEventManagerImpl::SendEvent Event Fire"); - __pEvent->FireAsync(*pEventArg); - r = E_SUCCESS; - } - - iter += sizeof(struct inotify_event) + pEvent->len; } - return r; + delete __pWatchList; + delete __pEvent; } result _FileEventManagerImpl::Construct(IFileEventListener& listener) { - GMainContext* pGContext = null; - result r = E_SUCCESS; - _FileEvent* pEvent = null; - __inotifyFd = inotify_init(); - - if (__inotifyFd == -1 && errno == EMFILE) - { - SysLogException(NID_IO, E_MAX_EXCEEDED, "The number of opened files has exceeded the maximum limit."); - return E_MAX_EXCEEDED; - } - SysTryReturnResult(NID_IO, __inotifyFd != -1, E_IO, "Failed to init inotify."); + unique_ptr< HashMap > pWatchList(new (std::nothrow) HashMap(SingleObjectDeleter)); + SysTryReturnResult(NID_IO, pWatchList != null, E_OUT_OF_MEMORY, "The memory is insufficient."); + pWatchList->Construct(); - unique_ptr pMonitorFileList(new (std::nothrow) HashMap()); - SysTryCatch(NID_IO, pMonitorFileList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to create monitored file list."); + unique_ptr< _FileEvent > pEvent(new (std::nothrow) _FileEvent()); + SysTryReturnResult(NID_IO, pEvent != null, E_OUT_OF_MEMORY, "The memory is insufficient."); - r = pMonitorFileList->Construct(); - SysTryCatch(NID_IO, r == E_SUCCESS, , r, "[%s] Propagated.", GetErrorMessage(r)); + result r = pEvent->AddListener(listener, true); + SysTryReturn(NID_IO, r == E_SUCCESS || r == E_OBJ_ALREADY_EXIST, E_IO, r, + "[%s] The caller thread is a worker thread.", GetErrorMessage(r)); - pGContext = g_main_context_get_thread_default(); //get own gmain context except default thread + _FileEventDispatcher* pDispatcher = _FileEventDispatcher::GetInstance(); + __inotifyFd = pDispatcher->GetInotifyFd(); + __pWatchList = pWatchList.release(); + __pEvent = pEvent.release(); - if (pGContext == null) - { - pGContext = g_main_context_default(); //get gmain context from me (default) - SysTryCatch(NID_IO, pGContext != null, r = E_IO, E_IO, "[E_IO] Failed to get glib context."); - } - - __pEvent = new (std::nothrow) _FileEvent(); - SysTryReturnResult(NID_IO, __pEvent != null, E_OUT_OF_MEMORY, "The memory is insufficient."); - - __pEvent->AddListener(listener); - - __pGIOChannel = g_io_channel_unix_new(__inotifyFd); //fd wrapping - SysTryCatch(NID_IO, __pGIOChannel != null, r = E_IO, E_IO, "[E_IO] Failed to create glib channel."); - - __pGSource = g_io_create_watch(__pGIOChannel, (GIOCondition)(G_IO_IN | G_IO_ERR | G_IO_NVAL | G_IO_HUP)); - SysTryCatch(NID_IO, __pGSource != null, r = E_IO, E_IO, "[E_IO] Failed to create glib watch."); - - g_source_set_callback(__pGSource, (GSourceFunc)OnFileEventOccured, this, NULL); - g_source_attach(__pGSource, pGContext); - - __pMonitorFileList = pMonitorFileList.release(); - - // fall thru -CATCH: - if (r != E_SUCCESS) - { - if (__inotifyFd != -1) - { - close(__inotifyFd); - } - - if (__pGIOChannel != null) - { - g_io_channel_unref(__pGIOChannel); - __pGIOChannel = null; - } - - if (__pGSource != null) - { - g_source_destroy(__pGSource); - g_source_unref(__pGSource); - __pGSource = null; - } - } - - return r; + SysLog(NID_IO, "_FileEventManagerImpl: 0x%x, _Event: 0x%x", this, __pEvent); + return E_SUCCESS; } result _FileEventManagerImpl::AddPath(const String& path, unsigned long eventsToMonitor) { - int monitoredFd = 0; + SysSecureLog(NID_IO, "Add watch path: %ls, _FileEventManagerImpl: 0x%x", path.GetPointer(), this); result r = E_SUCCESS; SysTryReturnResult(NID_IO, File::IsFileExist(path) == true, E_FILE_NOT_FOUND, - "path[%ls] dose not exist.", path.GetPointer()); - - SysLog(NID_IO, "path:%ls", path.GetPointer()); - - unique_ptr pPath(_StringConverter::CopyToCharArrayN(path)); - SysTryReturnResult(NID_IO, pPath != null, E_IO, "String covert is failed."); + "The path (%ls) dose not exist.", path.GetPointer()); - monitoredFd = inotify_add_watch(__inotifyFd, pPath.get(), eventsToMonitor); + unique_ptr< char[] > pPath(_StringConverter::CopyToCharArrayN(path)); + SysTryReturnResult(NID_IO, pPath != null, GetLastResult(), "Propagating to caller..."); - if (monitoredFd == -1) + int watchDescription = inotify_add_watch(__inotifyFd, pPath.get(), eventsToMonitor & ~IN_IGNORED); + if (watchDescription == -1) { r = E_IO; switch (errno) { case EACCES: - SysLogException(NID_IO, E_IO, "Read access to the given file[%s] is not permitted.", pPath.get()); + SysLogException(NID_IO, E_IO, "Read access to the given file (%s) is not permitted.", pPath.get()); r = E_ILLEGAL_ACCESS; break; case EFAULT: - SysLogException(NID_IO, E_IO, "The path[%s] points outside of the process's accessible address space.", pPath.get()); + SysLogException(NID_IO, E_IO, "The path (%s) points outside of the process's accessible address space.", pPath.get()); r = E_ILLEGAL_ACCESS; break; case EBADF: @@ -299,14 +145,40 @@ _FileEventManagerImpl::AddPath(const String& path, unsigned long eventsToMonitor return r; } - unique_ptr pMonitoredPath(new (std::nothrow) String(path)); - unique_ptr pMonitoredFd(new (std::nothrow) Integer(monitoredFd)); - SysTryReturnResult(NID_IO, pMonitoredPath != null && pMonitoredFd != null, E_IO, "Failed to allocate memory"); + Integer* pWatchDescription = new (std::nothrow) Integer(watchDescription); + _FileEventInfo* pFileEventInfo = new (std::nothrow) _FileEventInfo(); + String* pWatchPath = new (std::nothrow) String(path); + Integer* pWd = new (std::nothrow) Integer(watchDescription); + SysTryCatch(NID_IO, pWatchDescription != null && pFileEventInfo != null && pWatchPath != null && pWd != null, + r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "The memory is insufficient."); - SysTryReturnResult(NID_IO, __pMonitorFileList != null, E_IO, "Monitored file list is null"); + pFileEventInfo->pFileEventManagerImpl = this; + pFileEventInfo->path = path; - r = __pMonitorFileList->Add(*pMonitoredPath.release(), *pMonitoredFd.release()); - SysTryReturnResult(NID_IO, r == E_SUCCESS || r == E_OBJ_ALREADY_EXIST, E_IO, "Failed to add on monitored list."); + r = _FileEventDispatcher::GetInstance()->AddFileEventInfo(pWatchDescription, pFileEventInfo); + SysTryCatch(NID_IO, r == E_SUCCESS || r == E_OBJ_ALREADY_EXIST, r = E_IO, r, + "[%s] Failed to add file event info.", GetErrorMessage(r)); + if (r == E_OBJ_ALREADY_EXIST) + { + SysLog(NID_IO, "FileEventInfo already exists."); + delete pWatchDescription; + delete pFileEventInfo; + delete pWatchPath; + delete pWd; + } + else + { + SysLog(NID_IO, "Add to watch list"); + __pWatchList->Add(pWatchPath, pWd); + } + + return E_SUCCESS; + +CATCH: + delete pWatchDescription; + delete pFileEventInfo; + delete pWatchPath; + delete pWd; return r; } @@ -314,54 +186,20 @@ _FileEventManagerImpl::AddPath(const String& path, unsigned long eventsToMonitor result _FileEventManagerImpl::RemovePath(const String& path) { - Integer* pMonitoredFd = null; - - SysTryReturnResult(NID_IO, __pMonitorFileList != null, E_IO, "Monitored file list is null"); + SysSecureLog(NID_IO, "Remove watch path (%ls), _FileEventManagerImpl: 0x%x", path.GetPointer(), this); - pMonitoredFd = (Integer*)__pMonitorFileList->GetValue(path); + Integer* pWd = dynamic_cast< Integer* >(__pWatchList->GetValue(path)); + SysTryReturnResult(NID_IO, pWd != null, E_IO, "The path (%ls) is not registered.", path.GetPointer()); - SysTryReturnResult(NID_IO, pMonitoredFd != null, E_IO, "path[%ls] is not registered.", path.GetPointer()); + SysTryReturnResult(NID_IO, inotify_rm_watch(__inotifyFd, pWd->ToInt()) == 0, + E_IO, "The path (%ls) is not registered.", path.GetPointer()); - SysTryReturnResult(NID_IO, inotify_rm_watch(__inotifyFd, pMonitoredFd->ToInt()) == 0, - E_IO, "path[%ls] is not registered.", path.GetPointer()); + _FileEventDispatcher::GetInstance()->RemoveFileEventInfo(*pWd); + __pWatchList->Remove(path); - SysTryReturnResult(NID_IO, __pMonitorFileList->Remove(path, true) == E_SUCCESS, - E_IO, "path[%ls] is not registered.", path.GetPointer()); return E_SUCCESS; } -String -_FileEventManagerImpl::GetRegisteredPath(int fd) -{ - String* pRegisteredPath = null; - Integer* pRegisteredFD = null; - - if (__pMonitorFileList == null) - { - SysLog(NID_IO, "There is no path for fd:%d", fd); - return ""; - } - - unique_ptr pEnumerator(__pMonitorFileList->GetMapEnumeratorN()); - SysTryReturn(NID_IO, pEnumerator != null, L"", GetLastResult(), "[%s] Monitored file list is empty", GetErrorMessage(GetLastResult())); - - while (pEnumerator && pEnumerator->MoveNext() == E_SUCCESS) - { - pRegisteredPath = static_cast (pEnumerator->GetKey()); - pRegisteredFD = static_cast (pEnumerator->GetValue()); - - if (fd == pRegisteredFD->ToInt()) - { - SysLog(NID_IO, "Path is %ls", pRegisteredPath->GetPointer()); - return *pRegisteredPath; - } - - } - - SysLog(NID_IO, "There is no path for fd:%d", fd); - return ""; -} - _FileEventManagerImpl* _FileEventManagerImpl::GetInstance(FileEventManager& fileEventManager) { diff --git a/src/io/inc/FIo_FileEventManagerImpl.h b/src/io/inc/FIo_FileEventManagerImpl.h index 8f1e18c..c3bf019 100644 --- a/src/io/inc/FIo_FileEventManagerImpl.h +++ b/src/io/inc/FIo_FileEventManagerImpl.h @@ -24,11 +24,8 @@ #ifndef _FIO_INTERNAL_FILE_EVENT_MANAGER_IMPL_H_ #define _FIO_INTERNAL_FILE_EVENT_MANAGER_IMPL_H_ -#include - #include #include -#include #include namespace Tizen { namespace Base @@ -57,26 +54,24 @@ public: result RemovePath(const Tizen::Base::String& path); - result SendEvent(void); + Tizen::Base::Runtime::_Event* GetEvent(void) const + { + return __pEvent; + } static _FileEventManagerImpl* GetInstance(FileEventManager& fileEventManager); static const _FileEventManagerImpl* GetInstance(const FileEventManager& fileEventManager); private: - _FileEventManagerImpl(const _FileEventManagerImpl& source); - - _FileEventManagerImpl& operator =(const _FileEventManagerImpl& source); + _FileEventManagerImpl(const _FileEventManagerImpl& rhs); - Tizen::Base::String GetRegisteredPath(int fd); + _FileEventManagerImpl& operator =(const _FileEventManagerImpl& rhs); - static gboolean OnFileEventOccured(GIOChannel* source, GIOCondition condition, gpointer data); - - Tizen::Base::Collection::HashMap* __pMonitorFileList; +private: + Tizen::Base::Collection::HashMap* __pWatchList; Tizen::Base::Runtime::_Event* __pEvent; int __inotifyFd; - GSource* __pGSource; - GIOChannel* __pGIOChannel; friend class FileEventManager;