summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Friloux <guillaume.friloux@gmail.com>2013-12-16 13:38:00 +0100
committerGuillaume Friloux <guillaume.friloux@gmail.com>2013-12-16 13:38:00 +0100
commit57f2fc4c766e65d2d7a601ab52c9b761957ba8db (patch)
tree032677066b6b9de8add32b8b412f17723116e1cd
parentc8787af0cf251521e63bbee5717fe0d11c657f7d (diff)
Adding libspy.
It needs to be used by smman as this will consume less cpu cycles than managing inotify events. When having a lot of logs, inotify events gets too annoying, thus the fact that we miss some of them. With libspy, files will be polled periodically, no matter the activity on them.
-rw-r--r--configure.ac2
-rw-r--r--src/include/Spy.h25
-rw-r--r--src/lib/Makefile.mk12
-rw-r--r--src/lib/spy/spy_file.c208
-rw-r--r--src/lib/spy/spy_main.c157
-rw-r--r--src/lib/spy/spy_private.h44
6 files changed, 446 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index aaec67f..e34fd21 100644
--- a/configure.ac
+++ b/configure.ac
@@ -47,7 +47,7 @@ doc/Makefile
47]) 47])
48 48
49build_libs= 49build_libs=
50LIBS_REQUIRES="eina" 50LIBS_REQUIRES="eina ecore eio"
51PKG_CHECK_MODULES(LIBS, [$LIBS_REQUIRES], [build_libs=yes], [build_libs=no]) 51PKG_CHECK_MODULES(LIBS, [$LIBS_REQUIRES], [build_libs=yes], [build_libs=no])
52 52
53build_smman= 53build_smman=
diff --git a/src/include/Spy.h b/src/include/Spy.h
new file mode 100644
index 0000000..cc13da7
--- /dev/null
+++ b/src/include/Spy.h
@@ -0,0 +1,25 @@
1#ifndef SPY_H
2#define SPY_H
3#include <Eina.h>
4#include <Ecore.h>
5#include <Eio.h>
6
7extern int SPY_EVENT_LINE;
8
9typedef struct _Spy Spy;
10typedef struct _Spy_File Spy_File;
11typedef struct _Spy_Line Spy_Line;
12
13int spy_init(void);
14int spy_shutdown(void);
15
16Spy * spy_new(void);
17void spy_free(Spy *spy);
18
19Spy_File *spy_file_new(Spy *spy, const char *file);
20const char * spy_line_get(Spy_Line *sl);
21const char *spy_file_name_get(Spy_File *sf);
22void spy_file_data_set(Spy_File *sf, const void *data);
23const void *spy_file_data_get(Spy_File *sf);
24
25#endif
diff --git a/src/lib/Makefile.mk b/src/lib/Makefile.mk
index a4e2945..88771bb 100644
--- a/src/lib/Makefile.mk
+++ b/src/lib/Makefile.mk
@@ -1,10 +1,20 @@
1MAINTAINERCLEANFILES += src/lib/*.gc{no,da} 1MAINTAINERCLEANFILES += src/lib/*.gc{no,da}
2 2
3noinst_LTLIBRARIES = \ 3noinst_LTLIBRARIES = \
4src/lib/libconf.la 4src/lib/libconf.la \
5src/lib/libspy.la
5 6
6src_lib_libconf_la_SOURCES = \ 7src_lib_libconf_la_SOURCES = \
7src/lib/conf.c \ 8src/lib/conf.c \
8src/include/Conf.h 9src/include/Conf.h
9src_lib_libconf_la_CFLAGS = $(LIBS_CFLAGS) $(EXTRA_CPPFLAGS) 10src_lib_libconf_la_CFLAGS = $(LIBS_CFLAGS) $(EXTRA_CPPFLAGS)
10src_lib_libconf_la_LDFLAGS = $(LIBS_CFLAGS) 11src_lib_libconf_la_LDFLAGS = $(LIBS_CFLAGS)
12
13src_lib_libspy_la_SOURCES = \
14src/lib/spy/spy_file.c \
15src/lib/spy/spy_main.c \
16src/lib/spy/spy_private.h \
17src/include/Spy.h
18src_lib_libspy_la_CFLAGS = $(LIBS_CFLAGS) $(EXTRA_CPPFLAGS)
19src_lib_libspy_la_LDFLAGS = $(LIBS_CFLAGS)
20
diff --git a/src/lib/spy/spy_file.c b/src/lib/spy/spy_file.c
new file mode 100644
index 0000000..397862e
--- /dev/null
+++ b/src/lib/spy/spy_file.c
@@ -0,0 +1,208 @@
1#include "spy_private.h"
2
3static void
4_spy_file_job(void *data)
5{
6 spy_file_poll(data);
7}
8
9void
10_spy_file_line_free(void *d1,
11 void *d2 EINA_UNUSED)
12{
13 Spy_Line *sl = d1;
14
15 free((char *)sl->line);
16 free(sl);
17}
18
19void
20_spy_file_line_extract(Spy_File *sf)
21{
22 const char *s,
23 *p,
24 *p1;
25 size_t rm = 0;
26 Spy_Line *sl;
27
28 s = eina_strbuf_string_get(sf->read.buf);
29 p = s;
30
31 while ((p1=strchr(p, '\n')))
32 {
33 size_t l = p1 - p;
34 char *line;
35
36 rm += l;
37
38 if (!l)
39 goto end;
40
41 line = strndup(p, l);
42
43 DBG("Line = %s len=%zd", line, l);
44 sl = calloc(1, sizeof(Spy_Line));
45 if (!sl)
46 {
47 ERR("Failed to allocate Spy_Line");
48 free(line);
49 }
50
51 sl->sf = sf;
52 sl->line = line;
53 ecore_event_add(SPY_EVENT_LINE, sl, _spy_file_line_free, sl);
54 end:
55 p = p1 + 1;
56 }
57
58 eina_strbuf_remove(sf->read.buf, 0, rm);
59}
60
61void
62_spy_file_cb(void *data,
63 Ecore_Thread *thread EINA_UNUSED)
64{
65 Spy_File *sf;
66 size_t nbr = 0,
67 toread = 0,
68 left = 0;
69 char buf[512];
70
71 sf = data;
72 DBG("sf[%p]", sf);
73
74 sf->read.fd = fopen(sf->name, "r");
75 if (!sf->read.fd)
76 {
77 ERR("Failed to open %s : %s", sf->name, strerror(errno));
78 return;
79 }
80
81 fseeko(sf->read.fd, sf->read.offset, SEEK_SET);
82 left = sf->read.length;
83
84 while (nbr != (size_t)sf->read.length)
85 {
86 toread = (left < 512) ? left : 512;
87
88 if (fread(buf, toread, 1, sf->read.fd) != 1)
89 {
90 ERR("Error while reading file %s : %s",
91 sf->name, strerror(errno));
92 fclose(sf->read.fd);
93 return;
94 }
95 eina_strbuf_append_length(sf->read.buf, buf, toread);
96 _spy_file_line_extract(sf);
97 nbr += toread;
98 }
99 fclose(sf->read.fd);
100 sf->read.fd = NULL;
101}
102
103void
104_spy_file_end_cb(void *data,
105 Ecore_Thread *thread EINA_UNUSED)
106{
107 Spy_File *sf;
108
109 sf = data;
110 DBG("sf[%p]", sf);
111
112 ecore_timer_thaw(sf->poll.timer);
113 ecore_timer_reset(sf->poll.timer);
114
115 ecore_job_add(_spy_file_job, sf);
116}
117
118void
119_spy_file_cancel_cb(void *data EINA_UNUSED,
120 Ecore_Thread *thread EINA_UNUSED)
121{}
122
123Eina_Bool
124spy_file_poll(void *data)
125{
126 Spy_File *sf;
127 off_t size,
128 toread;
129 struct stat st;
130 Ecore_Thread *et;
131
132 sf = data;
133 DBG("spy_file[%p] file[%s]", sf, sf->name);
134
135 /* We should have different actions made depending on error type. */
136 if (stat(sf->name, &st))
137 {
138 ERR("Failed to get size of %s : %s", sf->name, strerror(errno));
139 return EINA_TRUE;
140 }
141
142 size = st.st_size;
143DBG("size=%zu", size);
144 if (sf->poll.size == size)
145 return EINA_TRUE;
146
147 /* File has been trunc! */
148 if (sf->poll.size > size)
149 {
150 DBG("spy_file[%p] File trunc!", sf);
151 sf->poll.size = 0;
152
153 if (!size)
154 return EINA_TRUE;
155 }
156
157 /* We have data to read! */
158 DBG("spy_file[%p] File activity!", sf);
159
160 toread = size - sf->poll.size;
161
162 DBG("spy_file[%p] len_old=%zu len_new=%zu toread=%zu",
163 sf, sf->poll.size, size, toread);
164
165 sf->read.offset = sf->poll.size;
166 sf->read.length = toread;
167
168
169 et = ecore_thread_run(_spy_file_cb,
170 _spy_file_end_cb,
171 _spy_file_cancel_cb,
172 sf);
173 if (!et)
174 {
175 ERR("Failed to create reading thread");
176 return EINA_TRUE;
177 }
178
179 ecore_timer_freeze(sf->poll.timer);
180 sf->poll.size = size;
181 return EINA_TRUE;
182}
183
184const char *
185spy_line_get(Spy_Line *sl)
186{
187 return sl->line;
188}
189
190
191const char *
192spy_file_name_get(Spy_File *sf)
193{
194 return sf->name;
195}
196
197void
198spy_file_data_set(Spy_File *sf,
199 const void *data)
200{
201 sf->data = (const void *)data;
202}
203
204const void *
205spy_file_data_get(Spy_File *sf)
206{
207 return sf->data;
208}
diff --git a/src/lib/spy/spy_main.c b/src/lib/spy/spy_main.c
new file mode 100644
index 0000000..8084050
--- /dev/null
+++ b/src/lib/spy/spy_main.c
@@ -0,0 +1,157 @@
1#include "spy_private.h"
2#include <sys/stat.h>
3#include <fcntl.h>
4#include <unistd.h>
5
6static int _spy_init_count = 0;
7int _spy_log_dom_global = -1;
8
9int SPY_EVENT_LINE = 0;
10
11Spy *
12spy_new(void)
13{
14 Spy *spy;
15
16 spy = calloc(1, sizeof(Spy));
17 DBG("spy[%p]", spy);
18 return spy;
19}
20
21void
22spy_free(Spy *spy)
23{
24 Eina_Inlist *l;
25 Spy_File *sf;
26 EINA_SAFETY_ON_NULL_RETURN(spy);
27
28 EINA_INLIST_FOREACH_SAFE(spy->files, l, sf)
29 {
30 free((char *)sf->name);
31 ecore_timer_del(sf->poll.timer);
32 eina_strbuf_free(sf->read.buf);
33 }
34 free(spy);
35}
36
37Spy_File *
38spy_file_new(Spy *spy, const char *file)
39{
40 Spy_File *sf;
41 struct stat st;
42
43 DBG("spy[%p] file[%s]", spy, file);
44
45 if (access(file, R_OK))
46 {
47 ERR("Failed to access %s : %s", file, strerror(errno));
48 return EINA_FALSE;
49 }
50
51 sf = calloc(1, sizeof(Spy_File));
52 if (!sf)
53 {
54 ERR("Failed to allocate Spy_File structure");
55 return EINA_FALSE;
56 }
57
58 sf->name = (const char *)strdup(file);
59 if (!sf->name)
60 {
61 ERR("Failed to dupe string \"%s\"", file);
62 goto free_sf;
63 }
64
65 if (stat(file, &st))
66 {
67 ERR("Failed to get size of %s : %s", file, strerror(errno));
68 goto free_name;
69 }
70
71 sf->read.buf = eina_strbuf_new();
72 if (!sf->read.buf)
73 {
74 ERR("Failed to create stringbuffer");
75 goto free_name;
76 }
77
78 sf->poll.size = st.st_size;
79 sf->poll.timer = ecore_timer_add(5.0, spy_file_poll, sf);
80
81 spy->files = eina_inlist_append(spy->files, EINA_INLIST_GET(sf));
82 DBG("spy_file[%p] size[%zd]", sf, st.st_size);
83 return sf;
84
85free_name:
86 free((char *)sf->name);
87free_sf:
88 free(sf);
89 return NULL;
90}
91
92
93int
94spy_init(void)
95{
96 if (++_spy_init_count != 1)
97 return _spy_init_count;
98
99 if (!eina_init())
100 {
101 fprintf(stderr, "Spy can not initialize Eina\n");
102 return --_spy_init_count;
103 }
104
105 _spy_log_dom_global = eina_log_domain_register("spy", EINA_COLOR_RED);
106 if (_spy_log_dom_global < 0)
107 {
108 EINA_LOG_ERR("Spy can not create a general log domain");
109 goto shutdown_eina;
110 }
111
112 if (!ecore_init())
113 {
114 ERR("Can not initialize Ecore");
115 goto unregister_log_domain;
116 }
117
118 if (!eio_init())
119 {
120 ERR("Can not initialize Eio");
121 goto shutdown_ecore;
122 }
123
124 SPY_EVENT_LINE = ecore_event_type_new();
125
126 return _spy_init_count;
127
128shutdown_ecore:
129 ecore_shutdown();
130unregister_log_domain:
131 eina_log_domain_unregister(_spy_log_dom_global);
132 _spy_log_dom_global = -1;
133shutdown_eina:
134 eina_shutdown();
135 return --_spy_init_count;
136}
137
138
139int
140spy_shutdown(void)
141{
142 if (_spy_init_count <= 0)
143 {
144 fprintf(stderr, "Spy init count not greater than 0 in shutdown.");
145 return 0;
146 }
147
148 if (--_spy_init_count != 0)
149 return _spy_init_count;
150
151 eio_shutdown();
152 ecore_shutdown();
153 eina_log_domain_unregister(_spy_log_dom_global);
154 _spy_log_dom_global = -1;
155 eina_shutdown();
156 return _spy_init_count;
157}
diff --git a/src/lib/spy/spy_private.h b/src/lib/spy/spy_private.h
new file mode 100644
index 0000000..287ea44
--- /dev/null
+++ b/src/lib/spy/spy_private.h
@@ -0,0 +1,44 @@
1#include <Spy.h>
2
3extern int _spy_log_dom_global;
4
5#define ERR(...) EINA_LOG_DOM_ERR(_spy_log_dom_global, __VA_ARGS__)
6#define DBG(...) EINA_LOG_DOM_DBG(_spy_log_dom_global, __VA_ARGS__)
7#define NFO(...) EINA_LOG_DOM_INFO(_spy_log_dom_global, __VA_ARGS__)
8#define WRN(...) EINA_LOG_DOM_WARN(_spy_log_dom_global, __VA_ARGS__)
9#define CRI(...) EINA_LOG_DOM_CRIT(_spy_log_dom_global, __VA_ARGS__)
10
11struct _Spy
12{
13 Eina_Inlist *files;
14};
15
16
17struct _Spy_File
18{
19 EINA_INLIST;
20 const char *name;
21 const void *data;
22
23 struct
24 {
25 Ecore_Timer *timer;
26 off_t size;
27 } poll;
28
29 struct
30 {
31 FILE *fd;
32 off_t offset,
33 length;
34 Eina_Strbuf *buf;
35 } read;
36};
37
38struct _Spy_Line
39{
40 Spy_File *sf;
41 const char *line;
42};
43
44Eina_Bool spy_file_poll(void *data);