Kannel: Open Source WAP and SMS gateway  svn-r5335
test_timerset.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * test_timerset.c - test Timerset objects
59  *
60  * Stipe Tolj <stolj at kannel.org>
61  */
62 
63 #include "gwlib/gwlib.h"
64 #include "gwlib/gw-timer.h"
65 #include "gw/msg.h"
66 
67 #define MAX_RETRY 3
68 #define FREQ 10
69 
70 typedef struct TimerItem {
71  Timer *timer;
72  Msg *msg;
73 } TimerItem;
74 
75 
76 static Timerset *timerset = NULL;
77 
78 static List *q_timer = NULL;
79 static List *q_retry = NULL;
80 
81 
82 /*
83  * This threads consumes the TimerItem events that the Timerset issues to the
84  * defined queue. In needs to use the lock-enabled calls, since it is an own
85  * thread context.
86  */
87 static void timer_consumer_thread(void *arg)
88 {
89  List *q = arg;
90  TimerItem *i;
91 
92  while ((i = gwlist_consume(q)) != NULL) {
93  if (++(i->msg->sms.resend_try) <= MAX_RETRY) {
95  debug("",0,"%s: Msg %p retry %ld", __func__,
96  i->msg, i->msg->sms.resend_try);
97  } else {
98  warning(0,"%s: Msg %p exceeded %d retries, discard!", __func__,
99  i->msg, MAX_RETRY);
100  msg_destroy(i->msg);
102  gw_free(i);
103  }
104  }
105 }
106 
107 
108 /*
109  * The callback function used by the Timerset when the event elapses. In case
110  * the timer is re-started within this callback function, then the
111  * gw_timer_elapsed_start_cb() needs to be used, otherwise we end-up in a
112  * dead-lock, due that the callback function runs in a thread that has the lock
113  * set already.
114  */
115 static void timer_retry_cb(void *arg)
116 {
117  TimerItem *i = arg;
118 
120 
122  gw_free(i);
123 }
124 
125 
126 /*
127  * The above timer_retry_cb() feeds a separate queue, which is consumed by
128  * this own threads, therefore we need to used the locking-enabled
129  * gw_timer_elapsed_start() to re-start a timer.
130  */
131 static void retry_consumer_thread(void *arg)
132 {
133  List *q = arg;
134  Msg *msg;
135  TimerItem *i;
136 
137  while ((msg = gwlist_consume(q)) != NULL) {
138  if (++(msg->sms.resend_try) <= MAX_RETRY) {
139  i = gw_malloc(sizeof(TimerItem));
140  i->msg = msg;
143  debug("",0,"%s: Msg %p retry %ld", __func__,
144  msg, msg->sms.resend_try);
145  } else {
146  warning(0,"%s: Msg %p exceeded %d retries, discard!", __func__,
147  msg, MAX_RETRY);
148  msg_destroy(msg);
149  }
150  }
151 }
152 
153 
154 int main()
155 {
156  long t_timer;
157  long t_retry;
158  Msg *msg_a, *msg_b;
159  TimerItem *i_timer;
160  TimerItem *i_retry;
161 
162  gwlib_init();
163 
165 
166  /* setup timer thread to consume queue */
170 
171  /* setup thread to consume retry callback events */
175 
176  msg_a = msg_create(sms);
177  msg_b = msg_create(sms);
178 
179  msg_a->sms.resend_try = msg_b->sms.resend_try = 0;
180 
181  i_timer = gw_malloc(sizeof(TimerItem));
182  i_timer->msg = msg_a;
183  /* timed events are pushed into q_timer queue */
184  i_timer->timer = gw_timer_create(timerset, q_timer, NULL);
185  gw_timer_elapsed_start(i_timer->timer, FREQ, i_timer);
186  debug("",0,"%s: Msg %p retry %ld", __func__, msg_a, msg_a->sms.resend_try);
187 
188  i_retry = gw_malloc(sizeof(TimerItem));
189  i_retry->msg = msg_b;
190  /* timed events trigged the callback function */
191  i_retry->timer = gw_timer_create(timerset, NULL, timer_retry_cb);
192  gw_timer_elapsed_start(i_retry->timer, FREQ, i_retry);
193  debug("",0,"%s: Msg %p retry %ld", __func__, msg_b, msg_b->sms.resend_try);
194 
195  debug("",0,"%s: enter main loop", __func__);
196  do {
197  gwthread_sleep(2);
198  } while (gw_timerset_count(timerset) > 0);
199  debug("",0,"%s: exit main loop", __func__);
200 
202 
204  gwthread_join(t_timer);
205  gwlist_destroy(q_timer, NULL);
206 
208  gwthread_join(t_retry);
209  gwlist_destroy(q_retry, NULL);
210 
211  gwlib_shutdown();
212 
213  return 0;
214 }
void gw_timerset_destroy(Timerset *set)
Definition: gw-timer.c:203
void gw_timer_elapsed_destroy_cb(Timer *timer)
Definition: gw-timer.c:295
#define MAX_RETRY
Definition: test_timerset.c:67
static List * q_timer
Definition: test_timerset.c:78
void gwlist_produce(List *list, void *item)
Definition: list.c:411
void gwthread_join(long thread)
long gw_timerset_count(Timerset *set)
Definition: gw-timer.c:244
Timer * gw_timer_create(Timerset *set, List *outputlist, void(*callback)(void *))
Definition: gw-timer.c:255
#define msg_create(type)
Definition: msg.h:136
int main()
Timerset * gw_timerset_create(void)
Definition: gw-timer.c:190
static void timer_retry_cb(void *arg)
Definition: msg.h:79
void gwlist_remove_producer(List *list)
Definition: list.c:401
void msg_destroy(Msg *msg)
Definition: msg.c:132
static List * q_retry
Definition: test_timerset.c:79
void warning(int err, const char *fmt,...)
Definition: log.c:660
static void retry_consumer_thread(void *arg)
#define gwthread_create(func, arg)
Definition: gwthread.h:90
struct TimerItem TimerItem
void gwthread_sleep(double seconds)
Timer * timer
Definition: smsbox.c:108
static void timer_consumer_thread(void *arg)
Definition: test_timerset.c:87
void gw_timer_elapsed_destroy(Timer *timer)
Definition: gw-timer.c:284
void * gwlist_consume(List *list)
Definition: list.c:427
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
void gw_timer_elapsed_start(Timer *timer, int interval, void *data)
Definition: gw-timer.c:352
void gwlib_shutdown(void)
Definition: gwlib.c:94
#define gwlist_create()
Definition: list.h:136
#define FREQ
Definition: test_timerset.c:68
void gwlib_init(void)
Definition: gwlib.c:78
static Timerset * timerset
Definition: test_timerset.c:76
void gwlist_add_producer(List *list)
Definition: list.c:383
Definition: list.c:102
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.