blob: cdbff3c5fb0a01f0fc4017b1e088758d094e972a [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
36FsWatcher::FsWatcher (QString dirPath, QObject* parent)
37 : QObject(parent)
38 , m_watcher (new QFileSystemWatcher())
39 , m_executor (1)
40 , m_dirPath (dirPath)
41{
42 _LOG_DEBUG ("Monitor dir: " << m_dirPath.toStdString ());
43 // add main directory to monitor
44 m_watcher->addPath (m_dirPath);
45
46 // register signals (callback functions)
47 connect (m_watcher, SIGNAL (directoryChanged (QString)), this, SLOT (DidDirectoryChanged (QString)));
48 connect (m_watcher, SIGNAL (fileChanged (QString)), this, SLOT (DidFileChanged (QString)));
49
50 m_executor.execute (bind (&FsWatcher::ScanDirectory_Notify_Execute, this, m_dirPath));
51}
52
53FsWatcher::~FsWatcher()
54{
55 delete m_watcher;
56}
57
58void
59FsWatcher::DidDirectoryChanged (QString dirPath)
60{
61 _LOG_DEBUG ("Triggered DirPath: " << dirPath.toStdString ());
62
63 m_executor.execute (bind (&FsWatcher::ScanDirectory_Notify_Execute, this, dirPath));
64}
65
66void
67FsWatcher::DidFileChanged (QString filePath)
68{
69 _LOG_DEBUG ("Triggered FilePath: " << filePath.toStdString ());
70}
71
72
73void FsWatcher::DidDirectoryChanged_Execute (QString dirPath)
74{
75// // scan directory and populate file list
76// QHash<QString, qint64> currentState = scanDirectory(dirPath);
77
78// // reconcile directory and report changes
79// std::vector<sEventInfo> dirChanges = reconcileDirectory(currentState, dirPath);
80// #ifdef _DEBUG
81// // DEBUG: Print Changes
82// printChanges(dirChanges);
83// #endif
84// // emit the signal if not empty
85// if(!dirChanges.empty())
86// emit dirEventSignal(dirChanges);
87}
88
89void
90FsWatcher::ScanDirectory_Notify_Execute (QString dirPath)
91{
92 QRegExp exclude ("^(\\.|\\.\\.|\\.chronoshare)$");
93
94 QDirIterator dirIterator (dirPath,
95 QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoSymLinks | QDir::NoDotAndDotDot,
96 QDirIterator::Subdirectories); // directory iterator (recursive)
97
98 // iterate through directory recursively
99 while (dirIterator.hasNext ())
100 {
101 dirIterator.next ();
102
103 // Get FileInfo
104 QFileInfo fileInfo = dirIterator.fileInfo ();
105
106 QString name = fileInfo.fileName ();
107
108 if (!exclude.exactMatch (name))
109 {
110 // _LOG_DEBUG ("Not excluded file/dir: " << fileInfo.absoluteFilePath ().toStdString ());
111 QString absFilePath = fileInfo.absoluteFilePath ();
112
113 // _LOG_DEBUG ("Attempt to add path to watcher: " << absFilePath.toStdString ());
114 m_watcher->addPath (absFilePath);
115
116 if (fileInfo.isFile ())
117 {
118 DidFileChanged (absFilePath);
119 }
120 // // if this is a directory
121 // if(fileInfo.isDir())
122 // {
123 // QStringList dirList = m_watcher->directories();
124
125 // // if the directory is not already being watched
126 // if (absFilePath.startsWith(m_dirPath) && !dirList.contains(absFilePath))
127 // {
128 // _LOG_DEBUG ("Add new dir to watchlist: " << absFilePath.toStdString ());
129 // // add this directory to the watch list
130 // m_watcher->addPath(absFilePath);
131 // }
132 // }
133 // else
134 // {
135 // _LOG_DEBUG ("Found file: " << absFilePath.toStdString ());
136 // // add this file to the file list
137 // // currentState.insert(absFilePath, fileInfo.created().toMSecsSinceEpoch());
138 // }
139 }
140 else
141 {
142 // _LOG_DEBUG ("Excluded file/dir: " << fileInfo.filePath ().toStdString ());
143 }
144 }
145}
146
147// std::vector<sEventInfo> FsWatcher::reconcileDirectory(QHash<QString, qint64> currentState, QString dirPath)
148// {
149// // list of files changed
150// std::vector<sEventInfo> dirChanges;
151
152// // compare result (database/stored snapshot) to fileList (current snapshot)
153// QMutableHashIterator<QString, qint64> i(m_storedState);
154
155// while(i.hasNext())
156// {
157// i.next();
158
159// QString absFilePath = i.key();
160// qint64 storedCreated = i.value();
161
162// // if this file is in a level higher than
163// // this directory, ignore
164// if(!absFilePath.startsWith(dirPath))
165// {
166// continue;
167// }
168
169// // check file existence
170// if(currentState.contains(absFilePath))
171// {
172// qint64 currentCreated = currentState.value(absFilePath);
173
174// if(storedCreated != currentCreated)
175// {
176// // update stored state
177// i.setValue(currentCreated);
178
179// // this file has been modified
180// sEventInfo eventInfo;
181// eventInfo.event = MODIFIED;
182// eventInfo.absFilePath = absFilePath.toStdString();
183// dirChanges.push_back(eventInfo);
184// }
185
186// // delete this file from fileList we have processed it
187// currentState.remove(absFilePath);
188// }
189// else
190// {
191// // delete from stored state
192// i.remove();
193
194// // this file has been deleted
195// sEventInfo eventInfo;
196// eventInfo.event = DELETED;
197// eventInfo.absFilePath = absFilePath.toStdString();
198// dirChanges.push_back(eventInfo);
199// }
200// }
201
202// // any files left in fileList have been added
203// for(QHash<QString, qint64>::iterator i = currentState.begin(); i != currentState.end(); ++i)
204// {
205// QString absFilePath = i.key();
206// qint64 currentCreated = i.value();
207
208// m_storedState.insert(absFilePath, currentCreated);
209
210// // this file has been added
211// sEventInfo eventInfo;
212// eventInfo.event = ADDED;
213// eventInfo.absFilePath = absFilePath.toStdString();
214// dirChanges.push_back(eventInfo);
215// }
216
217// return dirChanges;
218// }
219
220// QByteArray FsWatcher::calcChecksum(QString absFilePath)
221// {
222// // initialize checksum
223// QCryptographicHash crypto(QCryptographicHash::Md5);
224
225// // open file
226// QFile file(absFilePath);
227// file.open(QFile::ReadOnly);
228
229// // calculate checksum
230// while(!file.atEnd())
231// {
232// crypto.addData(file.read(8192));
233// }
234
235// return crypto.result();
236// }
237
238// void FsWatcher::printChanges(std::vector<sEventInfo> dirChanges)
239// {
240// if(!dirChanges.empty())
241// {
242// for(size_t i = 0; i < dirChanges.size(); i++)
243// {
244// QString tempString;
245
246// eEvent event = dirChanges[i].event;
247// QString absFilePath = QString::fromStdString(dirChanges[i].absFilePath);
248
249// switch(event)
250// {
251// case ADDED:
252// tempString.append("ADDED: ");
253// break;
254// case MODIFIED:
255// tempString.append("MODIFIED: ");
256// break;
257// case DELETED:
258// tempString.append("DELETED: ");
259// break;
260// }
261
262// tempString.append(absFilePath);
263
264// _LOG_DEBUG ("\t" << tempString.toStdString ());
265// }
266// }
267// else
268// {
269// _LOG_DEBUG ("\t[EMPTY]");
270// }
271// }
272
273#if WAF
274#include "fs-watcher.moc"
275#include "fs-watcher.cc.moc"
276#endif