Fwd: kqueue issues
Fwd: kqueue issues
- Subject: Fwd: kqueue issues
- From: "Foster Brereton" <email@hidden>
- Date: Wed, 12 Apr 2006 11:25:50 -0700
Hi all,
Thanks to the carbon-dev list I was directed to kqueues for file
notification support. I am trying to get a general file monitoring
registration mechanism up and running, one that leverages kqueue on
the back end (for MacOS X, anyhow; I'll be porting it to Win32 as well
so it's a cross-platform solution.)
I'm having issues with my kqueue implementation, however. I have looked over
the kqueue man pages and the PDF that comes alongside the
FileNotification example from Apple, still with no success.
The issue that I'm having is that the kevent never comes back telling
me an event has taken place. I have attached my code (it's not long,
and hopefully readable) and am wondering if someone can point out the
critical mistake I am making? I know there are other problems with the
code, but whatever it is that is keeping the kevents from firing is my
highest priority issue right now.
Thanks in advance for the help.
Blessings,
Foster
--
Foster T. Brereton - Computer Scientist
Software Technology Lab, Adobe Systems Incorporated
email@hidden -- http://opensource.adobe.com
/*
Copyright 2005-2006 Adobe Systems Incorporated
Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
or a copy at http://opensource.adobe.com/licenses.html)
*/
/****************************************************************************************************/
#include <adobe/future/file_monitor.hpp>
#include <adobe/algorithm.hpp>
#include <adobe/functional.hpp>
#include <adobe/once.hpp>
#include <boost/bind.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/thread/thread.hpp>
#include <list>
#include <vector>
#include <stdexcept>
#include <utility>
#include <sys/event.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <unistd.h>
/****************************************************************************************************/
ADOBE_GLOBAL_MUTEX_DEFINITION(file_monitor)
/****************************************************************************************************/
namespace {
/****************************************************************************************************/
inline u_int vnode_events()
{
return NOTE_DELETE | NOTE_WRITE |
NOTE_ATTRIB | NOTE_RENAME;
}
/****************************************************************************************************/
int file_monitor_kqueue()
{
static const int kq(kqueue());
if (kq < 0)
throw std::runtime_error("bad kqueue");
return kq;
}
/****************************************************************************************************/
struct file_t
{
typedef boost::filesystem::path path_type;
file_t(const path_type& path, const adobe::monitor_file_callback_t& proc) :
path_m(path), proc_m(proc)
{
static const timespec timeout = { 0, 0 };
fd_m = open(path_m.string().c_str(), O_EVTONLY); // WARNING (fbrereto) : is O_EVTONLY HFS+ only? (if so try FREAD)
EV_SET(&evt_m, fd_m, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, vnode_events(), 0, 0);
if (kevent(file_monitor_kqueue(), &evt_m, 1, NULL, 0, &timeout) == -1)
throw std::runtime_error("bad kevent");
}
~file_t()
{
static const timespec timeout = { 0, 0 };
evt_m.fflags = EV_DELETE;
if (kevent(file_monitor_kqueue(), &evt_m, 1, NULL, 0, &timeout) == -1)
throw std::runtime_error("bad kevent");
(void)close(fd_m);
}
path_type path_m;
adobe::monitor_file_callback_t proc_m;
int fd_m;
struct kevent evt_m;
};
typedef std::list<file_t> file_set_t;
/****************************************************************************************************/
file_set_t& file_set_nolock()
{
static file_set_t file_set_s;
return file_set_s;
}
/****************************************************************************************************/
inline file_set_t::iterator find_file_nolock(const boost::filesystem::path& path)
{
return adobe::find_if(file_set_nolock(), boost::bind(adobe::compare_members(&file_t::path_m,
std::equal_to<file_t::path_type>()),
_1, path));
}
/****************************************************************************************************/
void thread_monitor_loop()
{
static const timespec timeout = { 0, 0 }; // Time out 30 seconds, we check mpTaskInfo->done at leaset every 30 seconds
file_set_t& set(file_set_nolock());
if (!set.empty())
{
ADOBE_GLOBAL_MUTEX_INSTANCE(file_monitor);
int set_size(set.size());
std::vector<struct kevent> ev_receive(set_size);
while (set_size)
{
int ev_count = kevent(file_monitor_kqueue(), NULL, 0, &ev_receive[0], set_size, &timeout); // First call kevent specifying the number of folders to watch
if (ev_count <= 0)
break;
for (int i(0); i < ev_count; ++i)
{
struct kevent* kevp = &ev_receive[i];
if ( kevp->flags == EV_ERROR )
throw std::runtime_error("err");;
//PostKQueueEvent( kevp ); // Post kevent
}
}
}
}
/****************************************************************************************************/
void thread_monitor_proc()
{
while (true)
{
thread_monitor_loop();
}
}
/****************************************************************************************************/
} // namespace
/****************************************************************************************************/
namespace adobe {
/****************************************************************************************************/
void monitor(const boost::filesystem::path& path, const monitor_file_callback_t& proc)
{
if (proc.empty())
return;
if (!boost::filesystem::exists(path))
return;
static boost::thread::thread monitor_thread(&thread_monitor_proc);
ADOBE_GLOBAL_MUTEX_INSTANCE(file_monitor);
file_set_nolock().push_back(file_t(path, proc));
}
/****************************************************************************************************/
bool is_monitored(const boost::filesystem::path& path)
{
if (!boost::filesystem::exists(path))
return false;
ADOBE_GLOBAL_MUTEX_INSTANCE(file_monitor);
return find_file_nolock(path) != file_set_nolock().end();
}
/****************************************************************************************************/
void unmonitor(const boost::filesystem::path& path)
{
if (!boost::filesystem::exists(path))
return;
ADOBE_GLOBAL_MUTEX_INSTANCE(file_monitor);
file_set_t& set(file_set_nolock());
file_set_t::iterator result(find_file_nolock(path));
if (result == set.end())
return;
set.erase(result);
}
/****************************************************************************************************/
} // namespace adobe
/****************************************************************************************************/
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden