OSDN Git Service

initial TGitCache support added
[tortoisegit/TortoiseGitJp.git] / src / TGitCache / DirectoryWatcher.h
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // External Cache Copyright (C) 2005-2008 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #pragma once\r
20 #include "TGitPath.h"\r
21 #include "FolderCrawler.h"\r
22 #include "ShellCache.h"\r
23 \r
24 #define READ_DIR_CHANGE_BUFFER_SIZE 4096\r
25 \r
26 /**\r
27  * \ingroup TSVNCache\r
28  * Watches the file system for changes.\r
29  * When changes are detected, those changes are reported back to the CFolderCrawler\r
30  * which then can update the status cache.\r
31  *\r
32  * When a CDirectoryWatcher object is created, a new thread is started which\r
33  * waits for file system change notifications.\r
34  * To add folders to the list of watched folders, call \c AddPath().\r
35  *\r
36  * The folders are watched recursively. To prevent having too many folders watched,\r
37  * children of already watched folders are automatically removed from watching.\r
38  * This leads to having only the roots of file systems watched (e.g. C:\, D:\,...)\r
39  * after a few paths have been added to the watched list (at least, when the\r
40  * CGitStatusCache adds those paths).\r
41  */\r
42 class CDirectoryWatcher\r
43 {\r
44 public:\r
45         CDirectoryWatcher(void);\r
46         ~CDirectoryWatcher(void);\r
47         \r
48         /**\r
49          * Adds a new path to be watched. The path \b must point to a directory.\r
50          * If the path is already watched because a parent of that path is already\r
51          * watched recursively, then the new path is just ignored and the method\r
52          * returns false.\r
53          */\r
54         bool AddPath(const CTGitPath& path);\r
55         /**\r
56          * Removes a path and all its children from the watched list.\r
57          */\r
58         bool RemovePathAndChildren(const CTGitPath& path);\r
59         /**\r
60          * Checks if a path is watched\r
61          */\r
62         bool IsPathWatched(const CTGitPath& path);\r
63         \r
64         /**\r
65          * Returns the number of recursively watched paths.\r
66          */\r
67         int GetNumberOfWatchedPaths() {return watchedPaths.GetCount();}\r
68         \r
69         /**\r
70          * Sets the CFolderCrawler object which the change notifications are sent to.\r
71          */\r
72         void SetFolderCrawler(CFolderCrawler * crawler);\r
73         \r
74         /**\r
75          * Stops the watching thread.\r
76          */\r
77         void Stop();\r
78 \r
79         CTGitPath CloseInfoMap(HDEVNOTIFY hdev = INVALID_HANDLE_VALUE);\r
80         bool CloseHandlesForPath(const CTGitPath& path);\r
81 \r
82 private:\r
83         static unsigned int __stdcall ThreadEntry(void* pContext);\r
84         void WorkerThread();\r
85 \r
86         void ClearInfoMap();\r
87 \r
88         void BlockPath(const CTGitPath& path);\r
89 \r
90 private:\r
91         CComAutoCriticalSection m_critSec;\r
92         HANDLE                                  m_hThread;\r
93         HANDLE                                  m_hCompPort;\r
94         volatile LONG                   m_bRunning;\r
95 \r
96         CFolderCrawler *                m_FolderCrawler;        ///< where the change reports go to\r
97         \r
98         CTGitPathList                   watchedPaths;   ///< list of watched paths.\r
99 \r
100         CTGitPath                               blockedPath;\r
101         DWORD                                   blockTickCount;\r
102 \r
103         /**\r
104          * \ingroup TSVNCache\r
105          * Helper class: provides information about watched directories.\r
106          */\r
107         class CDirWatchInfo \r
108         {\r
109         private:\r
110                 CDirWatchInfo();        // private & not implemented\r
111                 CDirWatchInfo & operator=(const CDirWatchInfo & rhs);//so that they're aren't accidentally used. -- you'll get a linker error\r
112         public:\r
113                 CDirWatchInfo(HANDLE hDir, const CTGitPath& DirectoryName);\r
114                 ~CDirWatchInfo();\r
115 \r
116         protected:\r
117         public:\r
118                 bool    CloseDirectoryHandle();\r
119 \r
120                 HANDLE          m_hDir;                 ///< handle to the directory that we're watching\r
121                 CTGitPath       m_DirName;              ///< the directory that we're watching\r
122                 CHAR            m_Buffer[READ_DIR_CHANGE_BUFFER_SIZE]; ///< buffer for ReadDirectoryChangesW\r
123                 DWORD           m_dwBufLength;  ///< length or returned data from ReadDirectoryChangesW -- ignored?...\r
124                 OVERLAPPED  m_Overlapped;\r
125                 CString         m_DirPath;              ///< the directory name we're watching with a backslash at the end\r
126                 HDEVNOTIFY      m_hDevNotify;   ///< Notification handle\r
127         };\r
128 \r
129         std::map<HANDLE, CDirWatchInfo *> watchInfoMap;\r
130         \r
131         HDEVNOTIFY              m_hdev;\r
132 \r
133 };\r