source: xssim/branches/tpiontek/daemon/Daemon.cpp @ 104

Revision 104, 7.1 KB checked in by wojtekp, 13 years ago (diff)
  • Property svn:mime-type set to text/plain
Line 
1//============================================================================
2// Name        : Daemon.cpp
3// Author      : Jarek Szymczak
4// Version     :
5// Copyright   :
6// Description : Database data adding from files daemon
7//============================================================================
8
9#include <stdio.h>
10#include <cstdlib>
11#include <map>
12#include <iostream>
13#include <string>
14#include <fstream>
15#include <fcntl.h>
16#include <utility>
17#include <unistd.h>
18#include <errno.h>
19#include <signal.h>
20#include <string.h>
21#include <unistd.h>
22#include <sys/types.h>
23#include <sys/inotify.h>
24#include <sys/wait.h>
25
26using namespace std;
27
28#define EVENT_SIZE  ( sizeof (struct inotify_event) )
29#define EVENT_BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )
30#define RUNNING_DIR     "/opt/app/gssim/daemon"
31#define LOCK_FILE       "daemon.lock"
32#define LOG_FILE        "daemon.log"
33
34int fd;
35int length;
36int wd;
37char buffer[EVENT_BUF_LEN];
38char gssimdir[255];
39char gssimexecfile[255];
40char basedir[255];
41char msg[255];
42map<int, char*> paths;
43
44void log_message(const char *filename, const char *message)
45{
46FILE *logfile;
47        logfile=fopen(filename,"a");
48        if(!logfile) return;
49        fprintf(logfile,"%s\n",message);
50        fclose(logfile);
51}
52
53bool file_exists(const char * filename)
54{
55        if (FILE * file = fopen(filename, "r"))
56        {
57                fclose(file);
58                return true;
59        }
60       
61        return false;
62}
63
64void signal_handler(int sig)
65{
66        close(fd);
67        fclose (stdout);
68        fclose (stderr);
69
70        switch(sig) {
71        case SIGHUP:
72                log_message(LOG_FILE, "hangup signal catched");
73                break;
74        case SIGTERM:
75                log_message(LOG_FILE,"terminate signal catched");
76                exit(0);
77                break;
78        }
79}
80
81void daemonize()
82{
83        int i,lfp;
84        char str[10];
85
86        lfp=open(LOCK_FILE,O_RDWR|O_CREAT,0640);
87        if (lfp<0) exit(1); /* can not open */
88        if (lockf(lfp,F_TLOCK,0)<0)
89        {
90                cout << "Another instance of daemon is already running" << endl;
91                exit(-1); /* can not lock */
92        }
93        /* first instance continues */ 
94       
95        if(getppid()==1) return; /* already a daemon */
96        i=fork();
97        if (i<0) exit(1); /* fork error */
98        if (i>0) exit(0); /* parent exits */
99        /* child (daemon) continues */
100        setsid(); /* obtain a new process group */
101        //for (i=getdtablesize();i>=0;--i) close(i); /* close all descriptors */
102
103        close(0);
104        i=open("/dev/null",O_RDWR);
105        if(dup(i) < 0)
106        {
107                log_message(LOG_FILE, "Redirecting standard input to /dev/null failed");
108                exit(-1);
109        }
110       
111        if(freopen ("stdout.log","w",stdout) < 0)
112        {
113                log_message(LOG_FILE, "Redirecting standard output to stdout.log failed");
114                exit(-1);               
115        }
116       
117        if(freopen ("stderr.log","w",stderr) < 0)
118        {
119                log_message(LOG_FILE, "Redirecting standard error output to stderr.log failed");
120                exit(-1);               
121        }       
122       
123        umask(022); /* set newly created file permissions */
124        sprintf(str,"%d\n",getpid());
125        if(write(lfp,str,strlen(str)) < 0)
126        {
127                log_message(LOG_FILE, "couldn't record pid to lockfile");
128                exit(-1); /* record pid to lockfile */
129        }
130        signal(SIGCHLD,SIG_IGN); /* ignore child */
131        signal(SIGTSTP,SIG_IGN); /* ignore tty signals */
132        signal(SIGTTOU,SIG_IGN);
133        signal(SIGTTIN,SIG_IGN);
134        signal(SIGHUP,signal_handler); /* catch hangup signal */
135        signal(SIGTERM,signal_handler); /* catch kill signal */
136}
137
138void setup(int argc, char* argv[])
139{
140        if(chdir(RUNNING_DIR) < 0)
141        {
142                cout << "Couldn't change directory to running dir: " << RUNNING_DIR;
143                exit(-1);
144        } /* change running directory */
145       
146        char* config_file;
147       
148        if(argc > 0)
149                config_file = argv[0];
150        else
151                config_file = (char*)"daemon.config";
152       
153        ifstream fin(config_file);
154        if ( (fin.rdstate() & ifstream::failbit) != 0 )
155        {
156                        cerr << "Error while opening configuration file: " << config_file <<
157                        "current running dir: " << RUNNING_DIR << endl;
158                exit(-1);
159        }
160       
161        fin.getline(gssimdir, 255);
162        if ( (fin.rdstate() & (ifstream::failbit | ifstream::eofbit)) != 0 )
163        {
164                cerr << "Error while reading gssim dir" << endl;
165                exit(-1);
166        }
167
168        fin.getline(gssimexecfile, 255);
169        if ( (fin.rdstate() & (ifstream::failbit | ifstream::eofbit)) != 0 )
170        {
171                cerr << "Error while reading gssim exec file name" << endl;;
172                exit(-1);
173        }       
174       
175        fin.getline(basedir, 255);
176        if ( (fin.rdstate() & (ifstream::failbit | ifstream::eofbit)) != 0 )
177        {
178                cerr << "Error while reading base watch directory name" << endl;
179                exit(-1);
180        }       
181       
182        fin.close();
183
184        if(chdir(RUNNING_DIR) < 0)
185        {
186                cout << "Couldn't change directory to running dir: " << RUNNING_DIR;
187                exit(-1);
188        } /* change running directory */
189
190        signal(SIGINT, signal_handler);
191
192        /*creating the INOTIFY instance*/
193        fd = inotify_init();
194
195        /*checking for error*/
196        if (fd < 0) {
197                perror("inotify_init");
198        }
199
200        wd = inotify_add_watch(fd, basedir, IN_CREATE | IN_CLOSE_WRITE);
201        paths[wd] = basedir;
202       
203        strcpy(msg, "Directory ");
204        strcat(msg, basedir);
205        strcat(msg, " is added to watch list");
206        log_message(LOG_FILE, msg);
207}
208
209void monitor()
210{
211                while (1) {
212                       
213                int i = 0;
214
215                length = read(fd, buffer, EVENT_BUF_LEN);
216
217                if (length < 0) {
218                        log_message(LOG_FILE, "Severe error while monitoring occured (couldn't read event buffer)");
219                }
220
221                while (i < length) {
222                        struct inotify_event *event = (struct inotify_event *) &buffer[i];
223                        if (event->len) {
224                                if (event->mask & IN_CREATE) {
225                                        if (event->mask & IN_ISDIR) {
226
227                                                strcpy(msg, "New directory ");
228                                                strcat(msg, event->name);
229                                                strcat(msg, " created.");
230                                                log_message(LOG_FILE, msg);                                                             
231
232                                                char dir[255] = "\0";
233                                                strcat(dir, paths[event->wd]);
234                                                strcat(dir, "/");
235                                                strcat(dir, event->name);
236                                                wd = inotify_add_watch(fd, dir, IN_CREATE
237                                                                | IN_CLOSE_WRITE);
238                                                               
239                                                strcpy(msg, "Directory ");
240                                                strcat(msg, dir);
241                                                strcat(msg, " is added to watch list");                                                         
242                                                log_message(LOG_FILE, msg);                                                             
243                                                                                                               
244                                                paths[wd] = dir;
245                                        }
246                                } else if (event->mask & (IN_CLOSE_WRITE | IN_MOVED_TO)) {
247                                        string name = event->name;
248                                        char path[255];
249                                        strcpy(path, paths[event->wd]);
250                                                       
251                                        strcpy(msg, "File ");
252                                        strcat(msg, path);
253                                        strcat(msg, "/");
254                                        strcat(msg, name.c_str());             
255                                        strcat(msg, " writing is finished or file has just been moved.");                                               
256                                        log_message(LOG_FILE, msg);                                     
257                                                                               
258                                        int index = name.rfind(".tar");
259                                        if ((index + 4) == (int)name.length()) {
260
261                                                strcpy(msg, "Directory ");
262                                                strcat(msg, paths[event->wd]);
263                                                strcat(msg, "/");
264                                                strcat(msg, "is about to be erased from watch list");           
265                                                log_message(LOG_FILE, msg);                                                                     
266                                                       
267                                                paths.erase(event->wd);
268                                                inotify_rm_watch(fd, event->wd);
269                                                log_message(LOG_FILE, "Directory erased from watch list");
270                                                int pid = fork();
271                                                if (pid == 0) {
272                                                        if(chdir(gssimdir) < 0)
273                                                        {
274                                                                strcpy(msg, "Could not access gssim directory: ");
275                                                                strcat(msg, gssimdir);
276                                                                log_message(LOG_FILE, msg);                                                                             
277                                                        }
278                                                        char gssim[255] = "\0";
279                                                        strcpy(gssim, gssimdir);
280                                                        strcat(gssim, "/");
281                                                        strcat(gssim, gssimexecfile);
282                                                        strcat(path, "/");
283                                                        strcat(path, name.c_str());
284                                                        cout << gssim << endl << path << endl;
285                                                        execl(gssim, "gssim", path, NULL);
286                                                } else {
287                                                        waitpid(pid, NULL, 0);
288                                                        log_message(LOG_FILE, "Triggered operation finished");
289                                                }
290                                        }
291                                }
292                        }
293                        i += EVENT_SIZE + event->len;
294                }
295        }
296}
297
298int main(int argc, char* argv[]) {
299        setup(argc, argv);
300        daemonize();
301        cout << "log" << endl;
302        cerr << "logerr" << endl;
303        monitor();
304}
Note: See TracBrowser for help on using the repository browser.