blob: 2c6f8a214d402edb091d557d481897798e712475 [file] [log] [blame]
Alexander Afanasyev9e5a4702013-01-24 13:15:23 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2012-2013 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Jared Lindblom <lindblom@cs.ucla.edu>
19 * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
20 * Zhenkai Zhu <zhenkai@cs.ucla.edu>
21 */
22
23#include "fs-watcher.h"
24#include "logging.h"
25
26#include <boost/bind.hpp>
27
28#include <QDirIterator>
29#include <QRegExp>
30
31using namespace std;
32using namespace boost;
33
34INIT_LOGGER ("FsWatcher");
35
Alexander Afanasyev9ca444e2013-01-25 16:29:35 -080036FsWatcher::FsWatcher (QString dirPath,
37 LocalFile_Change_Callback onChange, LocalFile_Change_Callback onDelete,
38 QObject* parent)
Alexander Afanasyev9e5a4702013-01-24 13:15:23 -080039 : QObject(parent)
40 , m_watcher (new QFileSystemWatcher())
41 , m_executor (1)
42 , m_dirPath (dirPath)
Alexander Afanasyev9ca444e2013-01-25 16:29:35 -080043 , m_onChange (onChange)
44 , m_onDelete (onDelete)
Alexander Afanasyev9e5a4702013-01-24 13:15:23 -080045{
46 _LOG_DEBUG ("Monitor dir: " << m_dirPath.toStdString ());
47 // add main directory to monitor
48 m_watcher->addPath (m_dirPath);
49
50 // register signals (callback functions)
51 connect (m_watcher, SIGNAL (directoryChanged (QString)), this, SLOT (DidDirectoryChanged (QString)));
52 connect (m_watcher, SIGNAL (fileChanged (QString)), this, SLOT (DidFileChanged (QString)));
53
54 m_executor.execute (bind (&FsWatcher::ScanDirectory_Notify_Execute, this, m_dirPath));
Alexander Afanasyev5e140872013-01-24 23:58:10 -080055 m_executor.start ();
Alexander Afanasyev9e5a4702013-01-24 13:15:23 -080056}
57
58FsWatcher::~FsWatcher()
59{
Alexander Afanasyev5e140872013-01-24 23:58:10 -080060 m_executor.shutdown ();
Alexander Afanasyev9e5a4702013-01-24 13:15:23 -080061 delete m_watcher;
62}
63
64void
65FsWatcher::DidDirectoryChanged (QString dirPath)
66{
67 _LOG_DEBUG ("Triggered DirPath: " << dirPath.toStdString ());
68
69 m_executor.execute (bind (&FsWatcher::ScanDirectory_Notify_Execute, this, dirPath));
70}
71
72void
73FsWatcher::DidFileChanged (QString filePath)
74{
75 _LOG_DEBUG ("Triggered FilePath: " << filePath.toStdString ());
76}
77
78
79void FsWatcher::DidDirectoryChanged_Execute (QString dirPath)
80{
81// // scan directory and populate file list
82// QHash<QString, qint64> currentState = scanDirectory(dirPath);
83
84// // reconcile directory and report changes
85// std::vector<sEventInfo> dirChanges = reconcileDirectory(currentState, dirPath);
86// #ifdef _DEBUG
87// // DEBUG: Print Changes
88// printChanges(dirChanges);
89// #endif
90// // emit the signal if not empty
91// if(!dirChanges.empty())
92// emit dirEventSignal(dirChanges);
93}
94
95void
96FsWatcher::ScanDirectory_Notify_Execute (QString dirPath)
97{
98 QRegExp exclude ("^(\\.|\\.\\.|\\.chronoshare)$");
99
100 QDirIterator dirIterator (dirPath,
101 QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoSymLinks | QDir::NoDotAndDotDot,
102 QDirIterator::Subdirectories); // directory iterator (recursive)
103
104 // iterate through directory recursively
105 while (dirIterator.hasNext ())
106 {
107 dirIterator.next ();
108
109 // Get FileInfo
110 QFileInfo fileInfo = dirIterator.fileInfo ();
111
112 QString name = fileInfo.fileName ();
113
114 if (!exclude.exactMatch (name))
115 {
116 // _LOG_DEBUG ("Not excluded file/dir: " << fileInfo.absoluteFilePath ().toStdString ());
117 QString absFilePath = fileInfo.absoluteFilePath ();
118
119 // _LOG_DEBUG ("Attempt to add path to watcher: " << absFilePath.toStdString ());
120 m_watcher->addPath (absFilePath);
121
122 if (fileInfo.isFile ())
123 {
124 DidFileChanged (absFilePath);
125 }
126 // // if this is a directory
127 // if(fileInfo.isDir())
128 // {
129 // QStringList dirList = m_watcher->directories();
130
131 // // if the directory is not already being watched
132 // if (absFilePath.startsWith(m_dirPath) && !dirList.contains(absFilePath))
133 // {
134 // _LOG_DEBUG ("Add new dir to watchlist: " << absFilePath.toStdString ());
135 // // add this directory to the watch list
136 // m_watcher->addPath(absFilePath);
137 // }
138 // }
139 // else
140 // {
141 // _LOG_DEBUG ("Found file: " << absFilePath.toStdString ());
142 // // add this file to the file list
143 // // currentState.insert(absFilePath, fileInfo.created().toMSecsSinceEpoch());
144 // }
145 }
146 else
147 {
148 // _LOG_DEBUG ("Excluded file/dir: " << fileInfo.filePath ().toStdString ());
149 }
150 }
151}
152
153// std::vector<sEventInfo> FsWatcher::reconcileDirectory(QHash<QString, qint64> currentState, QString dirPath)
154// {
155// // list of files changed
156// std::vector<sEventInfo> dirChanges;
157
158// // compare result (database/stored snapshot) to fileList (current snapshot)
159// QMutableHashIterator<QString, qint64> i(m_storedState);
160
161// while(i.hasNext())
162// {
163// i.next();
164
165// QString absFilePath = i.key();
166// qint64 storedCreated = i.value();
167
168// // if this file is in a level higher than
169// // this directory, ignore
170// if(!absFilePath.startsWith(dirPath))
171// {
172// continue;
173// }
174
175// // check file existence
176// if(currentState.contains(absFilePath))
177// {
178// qint64 currentCreated = currentState.value(absFilePath);
179
180// if(storedCreated != currentCreated)
181// {
182// // update stored state
183// i.setValue(currentCreated);
184
185// // this file has been modified
186// sEventInfo eventInfo;
187// eventInfo.event = MODIFIED;
188// eventInfo.absFilePath = absFilePath.toStdString();
189// dirChanges.push_back(eventInfo);
190// }
191
192// // delete this file from fileList we have processed it
193// currentState.remove(absFilePath);
194// }
195// else
196// {
197// // delete from stored state
198// i.remove();
199
200// // this file has been deleted
201// sEventInfo eventInfo;
202// eventInfo.event = DELETED;
203// eventInfo.absFilePath = absFilePath.toStdString();
204// dirChanges.push_back(eventInfo);
205// }
206// }
207
208// // any files left in fileList have been added
209// for(QHash<QString, qint64>::iterator i = currentState.begin(); i != currentState.end(); ++i)
210// {
211// QString absFilePath = i.key();
212// qint64 currentCreated = i.value();
213
214// m_storedState.insert(absFilePath, currentCreated);
215
216// // this file has been added
217// sEventInfo eventInfo;
218// eventInfo.event = ADDED;
219// eventInfo.absFilePath = absFilePath.toStdString();
220// dirChanges.push_back(eventInfo);
221// }
222
223// return dirChanges;
224// }
225
226// QByteArray FsWatcher::calcChecksum(QString absFilePath)
227// {
228// // initialize checksum
229// QCryptographicHash crypto(QCryptographicHash::Md5);
230
231// // open file
232// QFile file(absFilePath);
233// file.open(QFile::ReadOnly);
234
235// // calculate checksum
236// while(!file.atEnd())
237// {
238// crypto.addData(file.read(8192));
239// }
240
241// return crypto.result();
242// }
243
244// void FsWatcher::printChanges(std::vector<sEventInfo> dirChanges)
245// {
246// if(!dirChanges.empty())
247// {
248// for(size_t i = 0; i < dirChanges.size(); i++)
249// {
250// QString tempString;
251
252// eEvent event = dirChanges[i].event;
253// QString absFilePath = QString::fromStdString(dirChanges[i].absFilePath);
254
255// switch(event)
256// {
257// case ADDED:
258// tempString.append("ADDED: ");
259// break;
260// case MODIFIED:
261// tempString.append("MODIFIED: ");
262// break;
263// case DELETED:
264// tempString.append("DELETED: ");
265// break;
266// }
267
268// tempString.append(absFilePath);
269
270// _LOG_DEBUG ("\t" << tempString.toStdString ());
271// }
272// }
273// else
274// {
275// _LOG_DEBUG ("\t[EMPTY]");
276// }
277// }
278
279#if WAF
280#include "fs-watcher.moc"
281#include "fs-watcher.cc.moc"
282#endif