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