Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff -ru --exclude=.svn incron-svn/appargs.cpp incron/appargs.cpp
- --- incron-svn/appargs.cpp 2012-02-03 11:34:52.255380477 +0100
- +++ incron/appargs.cpp 2012-02-03 11:45:30.327058000 +0100
- @@ -21,6 +21,7 @@
- #include <cstring>
- +#include <stdio.h>
- #include "strtok.h"
- diff -ru --exclude=.svn incron-svn/icd-main.cpp incron/icd-main.cpp
- --- incron-svn/icd-main.cpp 2012-02-03 11:34:52.254394984 +0100
- +++ incron/icd-main.cpp 2012-02-03 11:42:16.702707000 +0100
- @@ -24,6 +24,14 @@
- #include <sys/poll.h>
- #include <sys/stat.h>
- #include <cstring>
- +#ifdef WITH_MULTICAST_SUPPORT
- +# include <stdio.h>
- +# include <pthread.h>
- +# include <netinet/in.h>
- +# include <arpa/inet.h>
- +# include <stdlib.h>
- +# include <stdarg.h>
- +#endif
- #include "inotify-cxx.h"
- #include "appinst.h"
- @@ -79,6 +87,244 @@
- /// Daemonize true/false
- bool g_daemon = true;
- +/// Does it run as a master Node ?
- +volatile bool g_fMaster = true;
- +
- +#ifdef WITH_MULTICAST_SUPPORT
- +
- +/// mutex/cond/bool used to wait for network nodes before watching FS
- +pthread_mutex_t multiple_instance_mutex = PTHREAD_MUTEX_INITIALIZER;
- +pthread_cond_t multiple_instance_cond = PTHREAD_COND_INITIALIZER;
- +volatile bool g_threadRunning = false;
- +
- +/// used to exchange ID accross the network
- +typedef struct id_exchange {
- + uint32_t _magic; /// magic number to check application
- + uint32_t id; /// the id
- + uint32_t _mark; /// a random mark to identify sender
- +} id_exchange_t;
- +
- +#define _MAGIC (htonl(0xdeadbeef)) /// a random (but not too much) number
- +
- +/// a little helper function which print a string on console
- +/**
- + * Display a formatted string on stderr, if daemon mode is false
- + * \param[in] fmt formatted string, arguments follow
- + */
- +static void _debug(const char * fmt, ...) {
- +#ifdef DEBUG
- + if (!g_daemon) {
- + va_list vl;
- + va_start(vl, fmt);
- + vfprintf(stderr, fmt, vl);
- + va_end(vl);
- + fprintf(stderr, "\n");
- + }
- +#endif
- +}
- +
- +/// wait network read event on socket
- +/**
- + * \param[in] sock the socket on which we should wait for event
- + * \param[in] timeout how long ?
- + * \retval 0 timeout
- + * \retval 1 network read event handled
- + * \retval -1 network read error (other than EINTR)
- + */
- +int wait_network(int sock, double timeout = 1.0) {
- + fd_set read_fd;
- + FD_ZERO(&read_fd);
- + FD_SET(sock, &read_fd);
- + // one second timeout
- + struct timeval tv = { timeout, 0.0};
- + int max_fd = sock +1;
- + // select or timeout
- + int r;
- +
- + do {
- + r = select(max_fd, &read_fd, NULL, NULL, &tv);
- + } while (r == -1 && errno == EINTR);
- + return r;
- +}
- +
- +/// read network configuration as configured in file
- +int readNetworkConfiguration(struct sockaddr_in * addr_dest) {
- + if (!addr_dest)
- + return -1;
- + std::string cfgPeer;
- + std::string cfgPort;
- + bool r1 = false, r2 = false;
- + r1 = IncronCfg::GetValue("peer", cfgPeer);
- + r2 = IncronCfg::GetValue("listen_port", cfgPort);
- + memset(addr_dest, '\0', sizeof(*addr_dest));
- + addr_dest->sin_family = AF_INET;
- + addr_dest->sin_addr.s_addr = inet_addr(cfgPeer.c_str());
- + unsigned long uPort = strtoul(cfgPort.c_str(), NULL, 10);
- + addr_dest->sin_port = htons(uPort);
- + return 0;
- +}
- +
- +/// bind socket to the specified port
- +/** \param[in] port a NETWORK BYTE order port number
- + * \retval sock the socket bound to the port
- + * \retval -1 on error
- + */
- +int bindSocket(uint16_t port) {
- + sockaddr_in bind_addr;
- + unsigned char one = 1;
- +
- + int sock = socket(AF_INET, SOCK_DGRAM, 0);
- + if (sock == -1) {
- + syslog(LOG_CRIT, "Failed to create socket %m");
- + return sock;
- + }
- + setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one));
- +
- + memset(&bind_addr, '\0', sizeof(sockaddr_in));
- + bind_addr.sin_family = AF_INET;
- + bind_addr.sin_port = port; /* already in net order */
- + if (bind(sock, (struct sockaddr *)&bind_addr, sizeof(bind_addr))) {
- + syslog(LOG_CRIT, "Failed to bind socket %m");
- + close(sock);
- + sock = -1;
- + }
- + return sock;
- +}
- +/// Handle socket server
- +/** The thread routing which handle network event and master/slave mode
- + * \param[in] arg unused
- + */
- +void * networkServer(void * arg) {
- + srand((unsigned int)time(NULL)); // init random numbers, used later
- +
- + int hSocket = -1;
- +
- + // network initializations
- + sockaddr_in addr_dest;
- + readNetworkConfiguration(&addr_dest);
- +
- + id_exchange_t send_exchange = { _MAGIC, 0, rand() };
- + id_exchange_t recv_exchange = { 0, 0 };
- +
- + hSocket = bindSocket(addr_dest.sin_port);
- + if (hSocket == -1)
- + exit(1);
- +
- + if (IN_MULTICAST(addr_dest.sin_addr.s_addr)) {
- + unsigned char one = 1;
- + struct ip_mreq mreq;
- + memset(&mreq, '\0', sizeof(mreq));
- + mreq.imr_multiaddr = addr_dest.sin_addr;
- + if (setsockopt(hSocket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&one, sizeof(one)))
- + _debug("failed to set TTL");
- + if (setsockopt(hSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)))
- + _debug("failed to join multicast");
- + }
- +#define OTHER_ADDR_INIT(X) \
- + struct sockaddr_in X = { 0 }; \
- + (X).sin_family = AF_INET; \
- + socklen_t X ## _len = sizeof(X); \
- + (X).sin_addr.s_addr = htonl(INADDR_ANY)
- +
- + {
- + int r = wait_network(hSocket, 2.0);
- + if (r == 1) { // got something to read
- + OTHER_ADDR_INIT(other_addr);
- + r = recvfrom(hSocket, &recv_exchange, sizeof(recv_exchange), 0, (struct sockaddr *)&other_addr, &other_addr_len);
- + if (r == sizeof(recv_exchange) && recv_exchange._magic == _MAGIC) {
- + send_exchange.id = htonl(ntohl(recv_exchange.id)+10);
- + g_fMaster = false;
- + _debug("multiple nodes - slave mode");
- + } else {
- + _debug("bad node packet received");
- + syslog(LOG_CRIT, "bad packet received. Check network applications");
- + close(hSocket);
- + exit (1);
- + }
- + } else {
- + // no other nodes
- + send_exchange.id = htonl(10);
- + g_fMaster = true;
- + _debug("single node - master mode");
- + }
- + }
- +
- + // make the main thread running
- + pthread_mutex_lock(&multiple_instance_mutex);
- + g_threadRunning = true;
- + pthread_cond_broadcast(&multiple_instance_cond);
- + pthread_mutex_unlock(&multiple_instance_mutex);
- +
- + while (!g_fFinish) {
- + // master is sending keepalive each seconds
- + // slave is waiting for 2 seconds
- + int r = wait_network(hSocket, (g_fMaster ? 1.0 : 2.0));
- + if (r == 1) { // got something to read
- + OTHER_ADDR_INIT(other_addr);
- + r = recvfrom(hSocket, &recv_exchange, sizeof(recv_exchange), 0,
- + (struct sockaddr *)&other_addr, &other_addr_len);
- + if (other_addr.sin_addr.s_addr != 0) {
- +#ifdef DEBUG
- + {
- +#ifndef MAX
- +# define MAX(a,b) ((a) > (b) ? (a) : (b))
- +#endif
- + char addr[MAX(INET_ADDRSTRLEN,INET6_ADDRSTRLEN)] = { '\0' };
- + inet_ntop(other_addr.sin_family, &(other_addr.sin_addr),
- + addr, MAX(INET_ADDRSTRLEN,INET6_ADDRSTRLEN));
- + _debug("packet from %s", addr);
- + }
- +#endif
- + if (r == sizeof(recv_exchange) &&
- + recv_exchange._magic == _MAGIC &&
- + recv_exchange._mark != send_exchange._mark) {
- + /*
- + * the lowest ID is the master, unless if 0
- + * if the received ID (the "other") is lowest than mine,
- + * I am no more the master
- + * if the received ID is higher, I am still the master
- + * if both are equal, a new master is elected. I have to regenerate a new ID higher.
- + */
- + if (ntohl(recv_exchange.id) > ntohl(send_exchange.id)) {
- + _debug("got id %u, higher than mine %u: no changes (%s)",
- + ntohl(recv_exchange.id), ntohl(send_exchange.id),
- + (g_fMaster ? "master" : "slave"));
- + } else if (ntohl(recv_exchange.id) < ntohl(send_exchange.id)) {
- + _debug("got lower id %u, lower than mine %u: not master",
- + ntohl(recv_exchange.id), ntohl(send_exchange.id));
- + g_fMaster = false;
- + } else if (recv_exchange.id == send_exchange.id) {
- + _debug("Now a slave node (conflict)");
- + g_fMaster = false;
- + // generate a new id
- + send_exchange.id = rand();
- + sendto(hSocket, &send_exchange, sizeof(send_exchange), 0, (struct sockaddr *)&addr_dest, sizeof(addr_dest));
- + }
- + } else {
- + if (r == (signed int)sizeof(recv_exchange)) {
- + _debug ("-my pkt? - recv.magic = %x / .id = %u", ntohl(recv_exchange._magic), ntohl(recv_exchange.id));
- + }
- + // ignore other packets
- + }
- + } else {
- + _debug ("got a packet from 0.0.0.0 ?");
- + }
- + } else if (r == 0) {
- + // timeout
- + _debug("net timeout, sending keepalive, now master");
- + sendto(hSocket, &send_exchange, sizeof(send_exchange), 0, (struct sockaddr *)&addr_dest, sizeof(addr_dest));
- + g_fMaster = true;
- + } else if (r == -1) {
- + g_fMaster = false;
- + close(hSocket);
- + }
- + }
- + close(hSocket);
- + return NULL;
- +}
- +
- +#endif /* WITH_MULTICAST_SUPPORT */
- +
- /// Handles a signal.
- /**
- * For SIGTERM and SIGINT it sets the program finish variable.
- @@ -367,7 +613,7 @@
- if (access(sysBase.c_str(), R_OK) != 0) {
- syslog(LOG_CRIT, "cannot read directory for system tables (%s): (%i) %s", sysBase.c_str(), errno, strerror(errno));
- if (!g_daemon)
- - fprintf(stderr, "cannot read directory for system tables (%s): (%i) %s", sysBase.c_str(), errno, strerror(errno));
- + fprintf(stderr, "cannot read directory for system tables (%s): (%i) %s\n", sysBase.c_str(), errno, strerror(errno));
- ret = 1;
- goto error;
- }
- @@ -378,7 +624,7 @@
- if (access(userBase.c_str(), R_OK) != 0) {
- syslog(LOG_CRIT, "cannot read directory for user tables (%s): (%i) %s", userBase.c_str(), errno, strerror(errno));
- if (!g_daemon)
- - fprintf(stderr, "cannot read directory for user tables (%s): (%i) %s", userBase.c_str(), errno, strerror(errno));
- + fprintf(stderr, "cannot read directory for user tables (%s): (%i) %s\n", userBase.c_str(), errno, strerror(errno));
- ret = 1;
- goto error;
- }
- @@ -408,7 +654,44 @@
- goto error;
- }
- - prepare_pipe();
- + // IPG-NB ///////////////////////////////////////////////
- + /* create socket server and socket thread
- + * to synchronize between inotify instances
- + */
- + std::string cfgPeer;
- + std::string cfgPort;
- + bool r1 = false, r2 = false;
- + r1 = IncronCfg::GetValue("peer", cfgPeer);
- + r2 = IncronCfg::GetValue("listen_port", cfgPort);
- + if (r1 && r2) {
- + syslog(LOG_CRIT, "starting in multiple instances mode (%s:%s)", cfgPeer.c_str(), cfgPort.c_str());
- + if (!g_daemon)
- + fprintf(stderr, "starting in multiple instances mode (%s:%s)\n", cfgPeer.c_str(), cfgPort.c_str());
- + // disable running as a master node by default
- + g_fMaster = false;
- + pthread_mutex_lock(&multiple_instance_mutex);
- + pthread_t serverThread;
- + if (pthread_create (&serverThread, NULL, networkServer, NULL)) {
- + syslog(LOG_CRIT, "failed to start in multiple instances mode");
- + if (!g_daemon)
- + fprintf(stderr, "failed to start multiple instances mode\n");
- + ret = 1;
- + goto error;
- + }
- + // server thread started
- + while (!g_threadRunning) {
- + pthread_cond_wait(&multiple_instance_cond, &multiple_instance_mutex);
- + }
- + pthread_mutex_unlock(&multiple_instance_mutex);
- + if (!g_daemon)
- + fprintf(stderr, "starting monitoring\n");
- + } else {
- + g_threadRunning = true;
- + }
- +
- + // IPG-NB END ////////////////////////////////////////////
- +
- + prepare_pipe();
- Inotify in;
- in.SetNonBlock(true);
- @@ -443,7 +726,7 @@
- int res = poll(ed.GetPollData(), ed.GetSize(), -1);
- - if (res > 0) {
- + if (res > 0 && g_fMaster) {
- if (ed.ProcessEvents())
- UserTable::FinishDone();
- }
- diff -ru --exclude=.svn incron-svn/ict-main.cpp incron/ict-main.cpp
- --- incron-svn/ict-main.cpp 2012-02-03 11:34:52.257525597 +0100
- +++ incron/ict-main.cpp 2012-01-31 17:21:02.372338000 +0100
- @@ -49,7 +49,7 @@
- /// incrontab description string
- #define INCRONTAB_DESCRIPTION "incrontab - inotify cron table manipulator\n" \
- - "(c) Lukas Jelinek, 2006, 2007, 208"
- + "(c) Lukas Jelinek, 2006, 2007, 2008"
- /// incrontab help string
- #define INCRONTAB_HELP INCRONTAB_DESCRIPTION "\n\n" \
- diff -ru --exclude=.svn incron-svn/incroncfg.cpp incron/incroncfg.cpp
- --- incron-svn/incroncfg.cpp 2012-02-03 11:34:52.257525597 +0100
- +++ incron/incroncfg.cpp 2012-02-03 11:44:52.175537000 +0100
- @@ -41,6 +41,8 @@
- m_defaults.insert(CFG_MAP::value_type("lockfile_dir", "/var/run"));
- m_defaults.insert(CFG_MAP::value_type("lockfile_name", "incrond"));
- m_defaults.insert(CFG_MAP::value_type("editor", ""));
- + //m_defaults.insert(CFG_MAP::value_type("peer", "224.0.0.1"));
- + //m_defaults.insert(CFG_MAP::value_type("listen_port", "65001"));
- }
- void IncronCfg::Load(const std::string& rPath)
- @@ -181,7 +183,7 @@
- bool IncronCfg::IsComment(const char* s)
- {
- - char* sx = strchr(s, '#');
- + const char* sx = strchr(s, '#');
- if (sx == NULL)
- return false;
- diff -ru --exclude=.svn incron-svn/incron.conf.example incron/incron.conf.example
- --- incron-svn/incron.conf.example 2012-02-03 11:34:52.258380615 +0100
- +++ incron/incron.conf.example 2012-01-20 23:58:47.464186298 +0100
- @@ -70,3 +70,15 @@
- # Example:
- # editor = nano
- +# Parameter: peer
- +# Meaning: peer host watching the same filesystem / incrontable
- +# Description: Set this to an IP or FQDN of the incrond daemon running on
- +# another host, but watching same FS
- +# This is usefull if you need incrond running on 2 servers
- +# watching files on the same clusterFS
- +# Default: 127.0.0.1
- +#
- +# Example:
- +# peer = 192.168.1.2
- +
- +# listen_port = 65134
- diff -ru --exclude=.svn incron-svn/inotify-cxx.cpp incron/inotify-cxx.cpp
- --- incron-svn/inotify-cxx.cpp 2012-02-03 11:34:52.254394984 +0100
- +++ incron/inotify-cxx.cpp 2012-01-20 18:24:17.913326646 +0100
- @@ -23,6 +23,7 @@
- #include <errno.h>
- #include <unistd.h>
- #include <fcntl.h>
- +#include <stdio.h>
- #include "inotify-cxx.h"
- diff -ru --exclude=.svn incron-svn/Makefile incron/Makefile
- --- incron-svn/Makefile 2012-02-03 11:34:52.255380477 +0100
- +++ incron/Makefile 2012-02-03 11:48:59.914177655 +0100
- @@ -16,9 +16,11 @@
- DEBUG = -g0
- WARNINGS = -Wall
- CXXAUX = -pipe
- +OPTS = -DWITH_MULTICAST_SUPPORT=1
- +THREADS = -pthread
- -CXXFLAGS = $(OPTIMIZE) $(DEBUG) $(WARNINGS) $(CXXAUX)
- -LDFLAGS = $(WARNINGS)
- +CXXFLAGS = $(OPTIMIZE) $(DEBUG) $(WARNINGS) $(CXXAUX) $(OPTS) $(THREADS)
- +LDFLAGS = $(WARNINGS) $(THREADS)
- PROGRAMS = incrond incrontab
- diff -ru --exclude=.svn incron-svn/usertable.cpp incron/usertable.cpp
- --- incron-svn/usertable.cpp 2012-02-03 11:34:52.258380615 +0100
- +++ incron/usertable.cpp 2012-01-20 18:24:43.893078652 +0100
- @@ -27,6 +27,7 @@
- #include <stdlib.h>
- #include <sys/stat.h>
- #include <cstring>
- +#include <stdio.h>
- #include "usertable.h"
- #include "incroncfg.h"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement