Apply singleton pattern to reduce the number of used inotify instances.
authorHyunbin Lee <hyunbin.lee@samsung.com>
Thu, 9 May 2013 13:53:56 +0000 (22:53 +0900)
committerHyunbin Lee <hyunbin.lee@samsung.com>
Tue, 21 May 2013 08:50:10 +0000 (17:50 +0900)
Change-Id: I55b88c38b1ac3018182294850be15cfaf9c0c6ed
Signed-off-by: Hyunbin Lee <hyunbin.lee@samsung.com>
src/io/CMakeLists.txt
src/io/FIo_FileEvent.cpp [new file with mode: 0644]
src/io/FIo_FileEvent.h [new file with mode: 0644]
src/io/FIo_FileEventDispatcher.cpp [new file with mode: 0644]
src/io/FIo_FileEventDispatcher.h [new file with mode: 0644]
src/io/FIo_FileEventManagerImpl.cpp
src/io/inc/FIo_FileEventManagerImpl.h

index 3485c5d..098e03c 100644 (file)
@@ -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 (file)
index 0000000..607ce1c
--- /dev/null
@@ -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 <FBaseSysLog.h>
+#include <FIoIFileEventListener.h>
+#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<const _FileEventArg*>(&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 (file)
index 0000000..0a6e8a0
--- /dev/null
@@ -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 <FBaseRtIEventListener.h>
+#include <FBaseRtIEventArg.h>
+#include <FBaseRt_Event.h>
+
+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 (file)
index 0000000..3987029
--- /dev/null
@@ -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 <unique_ptr.h>
+#include <cstdlib>
+#include <sys/inotify.h>
+#include <string.h>
+#include <errno.h>
+
+#include <FBaseInteger.h>
+#include <FBaseColHashMap.h>
+#include <FBaseColLinkedList.h>
+#include <FBaseRtMutex.h>
+#include <FBaseSysLog.h>
+
+#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 (file)
index 0000000..00983b0
--- /dev/null
@@ -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 <glib.h>
+
+#include <FBaseInteger.h>
+#include <FBaseString.h>
+#include <FBaseColHashMap.h>
+
+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_
+
index 61da638..5fd8111 100644 (file)
 
 /**
  * @file       FIo_FileEventManager.cpp
- * @brief      This is the implementation file for FileEventManager class.
+ * @brief      This is the implementation file for _FileEventManager class.
  */
 
+#include <unique_ptr.h>
 #include <unistd.h>
 #include <sys/inotify.h>
 #include <errno.h>
-#include <new>
-#include <unique_ptr.h>
 
 #include <FBaseInteger.h>
 #include <FBaseString.h>
-#include <FBaseSysLog.h>
 #include <FBaseColAllElementsDeleter.h>
-#include <FBaseRtIEventArg.h>
+#include <FBaseColIMapEnumerator.h>
+#include <FBaseSysLog.h>
 #include <FIoFile.h>
-#include <FIoIFileEventListener.h>
 #include <FIoFileEventManager.h>
+#include <FIoIFileEventListener.h>
 
 #include <FBase_StringConverter.h>
 #include <FBase_NativeError.h>
-#include <FIo_FileEventManagerImpl.h>
-
-#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<IFileEventListener*> (&listener);
-                if (pListener != null)
-                {
-                        const _FileEventArg* pArg = dynamic_cast<const _FileEventArg*>(&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<unsigned long> (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<HashMap, AllElementsDeleter> 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<char[]> 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<String> pMonitoredPath(new (std::nothrow) String(path));
-       unique_ptr<Integer> 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<IMapEnumerator> 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<String*> (pEnumerator->GetKey());
-               pRegisteredFD = static_cast<Integer*> (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)
 {
index 8f1e18c..c3bf019 100644 (file)
 #ifndef _FIO_INTERNAL_FILE_EVENT_MANAGER_IMPL_H_
 #define _FIO_INTERNAL_FILE_EVENT_MANAGER_IMPL_H_
 
-#include <glib.h>
-
 #include <FBaseObject.h>
 #include <FBaseColHashMap.h>
-#include <FOspConfig.h>
 #include <FBaseRt_Event.h>
 
 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;