1 /* John McCutchan <jmccutchan@novell.com> 2005 */
2
3 #include "server_config.h"
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <unistd.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <glib.h>
12 #include "gam_protocol.h"
13 #include "gam_error.h"
14 #include "gam_eq.h"
15
16 // #define GAM_EQ_VERBOSE
17 typedef struct {
18 int reqno;
19 int event;
20 char *path;
21 int len;
22 } gam_eq_event_t;
23
24 static gam_eq_event_t *
gam_eq_event_new(int reqno,int event,const char * path,int len)25 gam_eq_event_new (int reqno, int event, const char *path, int len)
26 {
27 gam_eq_event_t *eq_event = NULL;
28
29 eq_event = g_new0(gam_eq_event_t, 1);
30 eq_event->reqno = reqno;
31 eq_event->event = event;
32 eq_event->path = g_strdup (path);
33 eq_event->len = len;
34
35 return eq_event;
36 }
37
38 static void
gam_eq_event_free(gam_eq_event_t * event)39 gam_eq_event_free (gam_eq_event_t *event)
40 {
41 if (!event)
42 return;
43
44 g_free (event->path);
45 g_free (event);
46 }
47
48 struct _gam_eq {
49 GQueue *event_queue;
50 };
51
52 gam_eq_t *
gam_eq_new(void)53 gam_eq_new (void)
54 {
55 gam_eq_t *eq = NULL;
56
57 eq = g_new0(struct _gam_eq, 1);
58 eq->event_queue = g_queue_new ();
59
60 return eq;
61 }
62
63 void
gam_eq_free(gam_eq_t * eq)64 gam_eq_free (gam_eq_t *eq)
65 {
66 if (!eq)
67 return;
68
69 while (!g_queue_is_empty (eq->event_queue))
70 {
71 gam_eq_event_t *event = g_queue_pop_head (eq->event_queue);
72 g_assert (event);
73 gam_eq_event_free (event);
74 }
75 g_queue_free (eq->event_queue);
76 g_free (eq);
77 }
78
79 void
gam_eq_queue(gam_eq_t * eq,int reqno,int event,const char * path,int len)80 gam_eq_queue (gam_eq_t *eq, int reqno, int event, const char *path, int len)
81 {
82 gam_eq_event_t *eq_event;
83
84 if (!eq)
85 return;
86
87 eq_event = g_queue_peek_tail (eq->event_queue);
88
89 /* Check if the last event in the event queue is the same as the one we are attempting to queue
90 * if it is, we can throw this new event away
91 */
92 if (eq_event && eq_event->reqno == reqno &&
93 eq_event->len == len &&
94 eq_event->event == event &&
95 !strcmp(eq_event->path, path))
96 {
97 #ifdef GAM_EQ_VERBOSE
98 GAM_DEBUG(DEBUG_INFO, "gam_eq: Didn't queue duplicate event\n");
99 #endif
100 return;
101 }
102 eq_event = gam_eq_event_new (reqno, event, path, len);
103 g_queue_push_tail (eq->event_queue, eq_event);
104 }
105
106 guint
gam_eq_size(gam_eq_t * eq)107 gam_eq_size (gam_eq_t *eq)
108 {
109 if (!eq)
110 return 0;
111
112 return g_queue_get_length (eq->event_queue);
113 }
114
115 static void
gam_eq_flush_callback(gam_eq_t * eq,gam_eq_event_t * event,GamConnDataPtr conn)116 gam_eq_flush_callback (gam_eq_t *eq, gam_eq_event_t *event, GamConnDataPtr conn)
117 {
118 gam_send_event (conn, event->reqno, event->event, event->path, event->len);
119 gam_eq_event_free (event);
120 }
121
122 gboolean
gam_eq_flush(gam_eq_t * eq,GamConnDataPtr conn)123 gam_eq_flush (gam_eq_t *eq, GamConnDataPtr conn)
124 {
125 gboolean done_work = FALSE;
126 if (!eq)
127 return FALSE;
128
129 #ifdef GAM_EQ_VERBOSE
130 GAM_DEBUG(DEBUG_INFO, "gam_eq: Flushing event queue for %s\n", gam_connection_get_pidname (conn));
131 #endif
132 while (!g_queue_is_empty (eq->event_queue))
133 {
134 done_work = TRUE;
135 gam_eq_event_t *event = g_queue_pop_head (eq->event_queue);
136 g_assert (event);
137 gam_eq_flush_callback (eq, event, conn);
138 }
139 return done_work;
140 }
141