summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordeva <deva>2010-01-07 07:14:33 +0000
committerdeva <deva>2010-01-07 07:14:33 +0000
commitb1268fe3acfa11e69dc909e8d9cceffe6745e452 (patch)
tree9cc2cc1548ed6af5ec90dc96821f4e01185abd1b
parent91988574b7b8d3ccdf186daee9a0f9c33b3803bb (diff)
Initial code for inotify wrapper class.
-rw-r--r--server/src/Makefile.am16
-rw-r--r--server/src/inotify.cc255
-rw-r--r--server/src/inotify.h76
3 files changed, 340 insertions, 7 deletions
diff --git a/server/src/Makefile.am b/server/src/Makefile.am
index ab49bf7..8d6e347 100644
--- a/server/src/Makefile.am
+++ b/server/src/Makefile.am
@@ -16,9 +16,7 @@ pracrod_SOURCES = \
debug.cc \
environment.cc \
exception.cc \
- queryhandlerpentominos.cc \
- queryhandlerpracro.cc \
- queryparser.cc \
+ inotify.cc \
journal_commit.cc \
journalwriter.cc \
log.cc \
@@ -31,6 +29,9 @@ pracrod_SOURCES = \
pracrodao.cc \
pracrodaopgsql.cc \
pracrodaotest.cc \
+ queryhandlerpentominos.cc \
+ queryhandlerpracro.cc \
+ queryparser.cc \
resumeparser.cc \
saxparser.cc \
semaphore.cc \
@@ -85,10 +86,7 @@ EXTRA_DIST = \
debug.h \
environment.h \
exception.h \
- queryhandler.h \
- queryhandlerpentominos.h \
- queryhandlerpracro.h \
- queryparser.h \
+ inotify.h \
journal_commit.h \
journalwriter.h \
log.h \
@@ -105,6 +103,10 @@ EXTRA_DIST = \
pracrodao.h \
pracrodaopgsql.h \
pracrodaotest.h \
+ queryhandler.h \
+ queryhandlerpentominos.h \
+ queryhandlerpracro.h \
+ queryparser.h \
resumeparser.h \
saxparser.h \
semaphore.h \
diff --git a/server/src/inotify.cc b/server/src/inotify.cc
new file mode 100644
index 0000000..f22e4ca
--- /dev/null
+++ b/server/src/inotify.cc
@@ -0,0 +1,255 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * inotify.cc
+ *
+ * Wed Jan 6 09:58:47 CET 2010
+ * Copyright 2010 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Pracro is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "inotify.h"
+
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+
+#define TEST(x, m) ((x & m) == m)
+
+static std::string mask2asc(uint32_t mask)
+{
+ // printf("mask: %x\n", mask);
+ std::string str;
+ if(TEST(mask, IN_ACCESS)) str += "File was accessed (read).";
+ if(TEST(mask, IN_ATTRIB)) str += "Metadata changed (permissions, timestamps, extended attributes, etc.).";
+ if(TEST(mask, IN_CLOSE_WRITE)) str += "File opened for writing was closed.";
+ if(TEST(mask, IN_CLOSE_NOWRITE)) str += "File not opened for writing was closed.";
+ if(TEST(mask, IN_CREATE)) str += "File/directory created in watched directory.";
+ if(TEST(mask, IN_DELETE)) str += "File/directory deleted from watched directory.";
+ if(TEST(mask, IN_DELETE_SELF)) str += "Watched file/directory was itself deleted.";
+ if(TEST(mask, IN_MODIFY)) str += "File was modified.";
+ if(TEST(mask, IN_MOVE_SELF)) str += "Watched file/directory was itself moved.";
+ if(TEST(mask, IN_MOVED_FROM)) str += "File moved out of watched directory.";
+ if(TEST(mask, IN_MOVED_TO)) str += "File moved into watched directory.";
+ if(TEST(mask, IN_OPEN)) str += "File was opened.";
+ if(TEST(mask, IN_ALL_EVENTS)) str += "All the above.";
+ return str;
+}
+
+static inline bool isdir(const char *name)
+{
+ struct stat s;
+ stat(name, &s);
+ return S_ISDIR(s.st_mode);
+}
+
+INotify::Event::Event(std::string name, uint32_t mask)
+{
+ this->_name = name;
+ this->_mask = mask;
+}
+
+bool INotify::Event::isCloseEvent()
+{
+ return TEST(_mask, IN_CLOSE_WRITE) || TEST(_mask, IN_CLOSE_NOWRITE);
+}
+
+bool INotify::Event::isOpenEvent()
+{
+ return TEST(_mask, IN_OPEN) || TEST(_mask, IN_CREATE);
+}
+
+bool INotify::Event::isModifyEvent()
+{
+ return TEST(_mask, IN_MODIFY);
+}
+
+bool INotify::Event::isDeleteEvent()
+{
+ return TEST(_mask, IN_DELETE) || TEST(_mask, IN_DELETE_SELF);
+}
+
+std::string INotify::Event::name()
+{
+ return _name;
+}
+
+uint32_t INotify::Event::mask()
+{
+ return _mask;
+}
+
+INotify::INotify()
+{
+ fd = inotify_init1(O_NONBLOCK);
+ if(fd == -1) {
+ perror("Inotify init failed.\n");
+ return;
+ }
+}
+
+INotify::~INotify()
+{
+ if(fd != -1) close(fd);
+}
+
+void INotify::add(std::string name, uint32_t mask)
+{
+ int _fd = inotify_add_watch(fd, name.c_str(), mask);
+ if(_fd == -1) {
+ perror("INotify: Add watch failed!");
+ return;
+ }
+ // dirmap[fd] = name;
+}
+
+void INotify::addRecursive(std::string name, uint32_t mask)
+{
+ /*
+ int fd = this->add(name, mask);
+ return fd;
+ */
+}
+
+void INotify::readEvents()
+{
+ char buf[sizeof(struct inotify_event)];
+ ssize_t r = 0;
+ while( (r = read(fd, buf, sizeof(buf))) > 0) {
+ struct inotify_event *event = (struct inotify_event *)buf;
+ /*
+ printf("--- Event ---:\n");
+ if(event->len) printf("Name: %s\n", event->name);
+ printf("Descriptor: %d\n", event->wd);
+ printf("Events:\n%s\n", mask2asc(event->mask).c_str());
+ */
+ eventlist.push_back(Event(event->name, event->mask));
+ /*
+ // Add watch on new subfolder.
+ if(TEST(event->mask, IN_CREATE) && isdir(event->name)) {
+ std::string fullpath = dirmap[event->wd] + "/" + event->name;
+ int fd = inotify_add_watch(watch, fullpath.c_str(), IN_ALL_EVENTS);
+ dirmap[fd] = fullpath;
+ }
+ */
+ /*
+ // Remove watch on deleted subfolder.
+ if(TEST(event->mask, IN_DELETE) && isdir(event->name)) {
+ inotify_add_watch(watch, event->name, IN_ALL_EVENTS);
+ }
+ */
+ }
+}
+
+bool INotify::hasEvents()
+{
+ readEvents();
+ return eventlist.size() > 0;
+}
+
+INotify::Event INotify::getNextEvent()
+{
+ readEvents();
+ if(eventlist.size()) {
+ Event event = eventlist.front();
+ eventlist.pop_front();
+ return event;
+ }
+ return Event("", 0);
+}
+
+void INotify::remove(int fd)
+{
+ inotify_rm_watch(this->fd, fd);
+}
+
+void INotify::remove(std::string name)
+{
+ // this->remove(rlookup(map, name))
+}
+
+#ifdef TEST_INOTIFY
+//deps: debug.cc
+//cflags: -I..
+//libs:
+#include "test.h"
+
+#include <stdio.h>
+
+#define _DIR "/tmp"
+#define _FILE _DIR"/inotify_test"
+
+TEST_BEGIN;
+
+INotify inotify;
+
+// Create file
+FILE *fp = fopen(_FILE, "w");
+TEST_NOTEQUAL(fp, NULL, "Testing if able to write file");
+fprintf(fp, "something");
+fclose(fp);
+
+inotify.add(_FILE);
+
+
+// Append to file
+fp = fopen(_FILE, "a");
+TEST_NOTEQUAL(fp, NULL, "Testing if able to write file");
+TEST_TRUE(inotify.hasEvents(), "Test if the open event was triggered.");
+TEST_TRUE(inotify.getNextEvent().isOpenEvent(), "Test if the event was an open event.");
+
+fprintf(fp, "else"); fflush(fp);
+TEST_TRUE(inotify.hasEvents(), "Test if the append event was triggered.");
+TEST_TRUE(inotify.getNextEvent().isModifyEvent(), "Test if the event was a modified event.");
+
+fclose(fp);
+TEST_TRUE(inotify.hasEvents(), "Test if the close event was triggered.");
+TEST_TRUE(inotify.getNextEvent().isCloseEvent(), "Test if the event was a close event.");
+
+
+// Overwrite file
+fp = fopen(_FILE, "w");
+TEST_NOTEQUAL(fp, NULL, "Testing if able to write file");
+TEST_TRUE(inotify.hasEvents(), "Test if the open event was triggered.");
+TEST_TRUE(inotify.getNextEvent().isOpenEvent(), "Test if the event was an open event.");
+
+fprintf(fp, "else"); fflush(fp);
+TEST_TRUE(inotify.hasEvents(), "Test if the append event was triggered.");
+TEST_TRUE(inotify.getNextEvent().isModifyEvent(), "Test if the event was a modified event.");
+
+fclose(fp);
+TEST_TRUE(inotify.hasEvents(), "Test if the close event was triggered.");
+TEST_TRUE(inotify.getNextEvent().isCloseEvent(), "Test if the event was a close event.");
+
+
+// Delete file
+unlink(_FILE);
+
+TEST_EQUAL(inotify.hasEvents(), true, "Test if the delete event was triggered.");
+TEST_EQUAL(inotify.getNextEvent().isDeleteEvent(), true, "Test if the event was a delete event.");
+
+mask2asc(0);
+
+TEST_END;
+
+#endif/*TEST_INOTIFY*/
diff --git a/server/src/inotify.h b/server/src/inotify.h
new file mode 100644
index 0000000..f6126ed
--- /dev/null
+++ b/server/src/inotify.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * inotify.h
+ *
+ * Wed Jan 6 09:58:47 CET 2010
+ * Copyright 2010 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Pracro is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __PRACRO_INOTIFY_H__
+#define __PRACRO_INOTIFY_H__
+
+#include <sys/types.h>
+#include <sys/inotify.h>
+
+#include <string>
+#include <map>
+#include <list>
+
+class INotify {
+public:
+ class Event {
+ public:
+ Event(std::string name, uint32_t mask);
+
+ bool isOpenEvent();
+ bool isCloseEvent();
+ bool isModifyEvent();
+ bool isDeleteEvent();
+
+ std::string name();
+ uint32_t mask();
+
+ private:
+ std::string _name;
+ uint32_t _mask;
+ };
+
+ INotify();
+ ~INotify();
+
+ void add(std::string name, uint32_t mask = IN_ALL_EVENTS);
+ void remove(std::string name);
+ void remove(int fd);
+
+ void addRecursive(std::string name, uint32_t mask = IN_ALL_EVENTS);
+
+ bool hasEvents();
+ Event getNextEvent();
+
+private:
+ void readEvents();
+ int fd;
+ std::map<int, std::string> dirmap;
+ std::list<Event> eventlist;
+};
+
+#endif/*__PRACRO_INOTIFY_H__*/