OSDN Git Service

Update INSTALL.ja.utf-8 for new release.
[ultramonkey-l7/ultramonkey-l7-v2.git] / src / sched.c
1 /*
2  * @file  sched.c
3  * @brief the framework module of scheduer 
4  * @brief it proceeds common function of scheduler 
5  *
6  * L7VSD: Linux Virtual Server for Layer7 Load Balancing
7  * Copyright (C) 2005  NTT COMWARE Corporation.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22  * 02110-1301 USA
23  *
24  **********************************************************************/
25
26 #include <string.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <glib.h>
32
33 #include "l7vs_sched.h"
34 #include "l7vs_service.h"
35 #include "l7vs_module.h"
36 #include "l7vs_dest.h"
37 #include "logger_wrapper.h"
38
39 static struct l7vs_scheduler *l7vs_sched_load(char *name);
40 static void l7vs_sched_unload(struct l7vs_scheduler *sched);
41 static struct l7vs_scheduler *l7vs_sched_lookup(char *name);
42 static gint l7vs_sched_cmp(struct l7vs_scheduler *sched, char *name);
43
44 static GList *l7vs_sched_list = NULL;
45
46 /*!
47  * Get scheduler module.
48  * @param[in]   *name           scheduler module name
49  * @return      struct l7vs_scheduler*  OK=scheduler pointer, NG=NULL
50  */
51 struct l7vs_scheduler *
52 l7vs_sched_get(char *name)
53 {
54         struct l7vs_scheduler *sched = NULL;
55
56         /*-------- DEBUG LOG --------*/
57         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
58                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,3,
59                     "in_function: struct l7vs_scheduler* l7vs_sched_get(char* name): name=\"%s\"", name);
60         }
61         /*------ DEBUG LOG END ------*/
62
63         // argment check
64         if (name == NULL) {
65                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,2,
66                     "Scheduler module name is NULL");
67                 goto get_out;
68         }
69         sched = l7vs_sched_lookup(name);
70         if (sched == NULL) {
71                 sched = l7vs_sched_load(name);
72                 if (sched == NULL) {
73                         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,3,
74                                                  "Scheduler module not found maybe module problem)");
75                         goto get_out;
76                 }
77                 sched->refcnt = 0;
78         }
79
80         sched->refcnt++;
81
82 get_out:
83         /*-------- DEBUG LOG --------*/
84         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
85                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,4,
86                     "out_function: struct l7vs_scheduler* l7vs_sched_get(char* name): return_value=%p", sched);
87         }
88         /*------ DEBUG LOG END ------*/
89
90         return sched;
91 }
92
93 /*!
94  * Put scheduler module.
95  * @param[in]   *sched          scheduler pointer
96  * @return      void
97  */
98 void
99 l7vs_sched_put(struct l7vs_scheduler *sched)
100 {
101         /*-------- DEBUG LOG --------*/
102         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
103                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,5,
104                     "in_function: void l7vs_sched_put(struct l7vs_scheduler* sched): sched=%p", sched);
105         }
106         /*------ DEBUG LOG END ------*/
107
108         // argument check
109         if (sched == NULL) {
110                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,4,
111                     "Arg(sched) is NULL pointer.");
112                 goto put_out;
113         }
114
115         if (--sched->refcnt <= 0) {
116                 l7vs_module_remove(&l7vs_sched_list, sched);
117                 l7vs_sched_unload(sched);
118         }
119
120 put_out:
121         /*-------- DEBUG LOG --------*/
122         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
123                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,6,
124                     "out_function: void l7vs_sched_put(struct l7vs_scheduler* sched)");
125         }
126         /*------ DEBUG LOG END ------*/
127
128 }
129
130 /*!
131  * Bind scheduler module to service.
132  * @param[in]   *sched          scheduler pointer
133  * @param[in]   *svc            service pointer
134  * @return      void
135  */
136 void
137 l7vs_sched_bind(struct l7vs_scheduler *sched,
138                 struct l7vs_service *svc)
139 {
140         /*-------- DEBUG LOG --------*/
141         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
142                 char srv_str[DEBUG_STR_LEN] = {0};
143                 l7vs_service_c_str(srv_str, svc);
144                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,7,
145                     "in_function: void l7vs_sched_bind(struct l7vs_scheduler* sched, struct l7vs_service* svc): sched=%p, svc=&(%s)", sched, srv_str);
146         }
147         /*------ DEBUG LOG END ------*/
148
149         // argument check
150         if (sched && svc) {
151                 svc->scheduler = sched;
152                 if (sched->bind != NULL) {
153                         sched->bind(svc);
154                 }
155         }
156
157         /*-------- DEBUG LOG --------*/
158         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
159                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,8,
160                     "out_function: void l7vs_sched_bind(struct l7vs_scheduler* sched, struct l7vs_service* svc)");
161         }
162         /*------ DEBUG LOG END ------*/
163 }
164
165 /*!
166  * Unbind scheduler module form service.
167  * @param[in]   *sched          scheduler pointer
168  * @param[in]   *svc            service pointer
169  * @return      void
170  */
171 void
172 l7vs_sched_unbind(struct l7vs_scheduler *sched,
173                   struct l7vs_service *svc)
174 {
175         /*-------- DEBUG LOG --------*/
176         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
177                 char srv_str[DEBUG_STR_LEN] = {0};
178                 l7vs_service_c_str(srv_str, svc);
179                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,9,
180                     "in_function: void l7vs_sched_unbind(struct l7vs_scheduler* sched, struct l7vs_service* svc): sched=%p, svc=&(%s)", sched, srv_str);
181         }
182         /*------ DEBUG LOG END ------*/
183
184         // argument check
185         if (sched && svc) {
186                 svc->scheduler = NULL;
187                 if (sched->unbind != NULL) {
188                         sched->unbind(svc);
189                 }
190         }
191
192         /*-------- DEBUG LOG --------*/
193         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
194                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,10,
195                     "out_function: void l7vs_sched_unbind(struct l7vs_scheduler* sched, struct l7vs_service* svc)");
196         }
197         /*------ DEBUG LOG END ------*/
198 }
199
200 /*!
201  * Load scheduler module.
202  * @param[in]   *name           scheduler module name
203  * @return      struct l7vs_scheduler*  OK=scheduler pointer, NG=NULL
204  */
205 static struct l7vs_scheduler *
206 l7vs_sched_load(char *name)
207 {
208         struct l7vs_scheduler *sched = NULL;
209
210         /*-------- DEBUG LOG --------*/
211         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
212                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,11,
213                     "in_function: struct l7vs_scheduler* l7vs_sched_load(char* name): name=\"%s\"", name);
214         }
215         /*------ DEBUG LOG END ------*/
216
217         // argment check
218         if (name == NULL) {
219                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,5,
220                     "Scheduler module name is NULL");
221                 goto load_out;
222         }
223         sched = (struct l7vs_scheduler *)l7vs_module_load(name, "sched");
224         if (sched == NULL) {
225                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,6,
226                     "Module load error.");
227                 goto load_out;
228         }
229         sched->get_log_level = logger_get_log_level;
230         sched->put_log_debug = logger_put_log_debug;
231         sched->put_log_info = logger_put_log_info;
232         sched->put_log_warn = logger_put_log_warn;
233         sched->put_log_error = logger_put_log_error;
234         sched->put_log_debug = logger_put_log_debug;
235
236         l7vs_module_register(&l7vs_sched_list, sched);
237
238 load_out:
239         /*-------- DEBUG LOG --------*/
240         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
241                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,12,
242                     "out_function: struct l7vs_scheduler* l7vs_sched_load(char* name): return_value=%p", sched);
243         }
244         /*------ DEBUG LOG END ------*/
245
246         return sched;
247 }
248
249 /*!
250  * Unload scheduler module.
251  * @param[in]   *sched          scheduler pointer
252  * @return      void
253  */
254 static void
255 l7vs_sched_unload(struct l7vs_scheduler *sched)
256 {
257         void *h;
258
259         /*-------- DEBUG LOG --------*/
260         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
261                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,13,
262                     "in_function: void l7vs_sched_unload(struct l7vs_scheduler* sched): sched=%p", sched);
263         }
264         /*------ DEBUG LOG END ------*/
265
266         // argument check
267         if (sched == NULL) {
268                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,7,
269                     "Arg(sched) is NULL pointer.");
270                 goto unload_out;
271         }
272
273         h = sched->handle;
274         if (sched->fini) {
275                 sched->fini();
276         }
277         l7vs_module_unload(h);
278
279 unload_out:
280         /*-------- DEBUG LOG --------*/
281         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
282                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,14,
283                     "out_function: void l7vs_sched_unload(struct l7vs_scheduler* sched)");
284         }
285         /*------ DEBUG LOG END ------*/
286 }
287
288 /*!
289  * Lookup scheduler module in sched_list.
290  * @param[in]   *name           scheduler module name
291  * @return      struct l7vs_scheduler*  found=scheduler pointer, not found=NULL
292  */
293 static struct l7vs_scheduler *
294 l7vs_sched_lookup(char *name)
295 {
296         struct l7vs_scheduler* sched = NULL;
297
298         /*-------- DEBUG LOG --------*/
299         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
300                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,15,
301                     "in_function: struct l7vs_scheduler* l7vs_sched_lookup(char* name): "
302                     "name=\"%s\"", name);
303         }
304         /*------ DEBUG LOG END ------*/
305
306         // argment check
307         if (name == NULL) {
308                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,8,
309                     "Scheduler module name is NULL");
310                 goto lookup_out;
311         }
312
313         sched = (struct l7vs_scheduler *) l7vs_module_lookup(l7vs_sched_list, name,
314             (GCompareFunc) l7vs_sched_cmp);
315
316 lookup_out:
317         /*-------- DEBUG LOG --------*/
318         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
319                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,16,
320                     "out_function: struct l7vs_scheduler* l7vs_sched_load(char* name): "
321                     "return_value=%p", sched);
322         }
323         /*------ DEBUG LOG END ------*/
324
325         return sched;
326 }
327
328 /*!
329  * Compare scheduler module name.
330  * @param[in]   *sched          scheduler pointer
331  * @param[in]   *name           scheduler module name
332  * @return      gint            compare result match=0, not match=-1 or other
333  */
334 static gint
335 l7vs_sched_cmp(struct l7vs_scheduler *sched, char *name)
336 {
337         gint return_value;
338
339         /*-------- DEBUG LOG --------*/
340         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
341                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,17,
342                     "in_function: gint l7vs_sched_cmp(struct l7vs_scheduler* sched, char* name): "
343                     "sched=%p, name=\"%s\"", sched, name);
344         }
345         /*------ DEBUG LOG END ------*/
346
347         // argument check
348         if (sched == NULL) {
349                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,9,
350                     "Arg(sched) is NULL pointer.");
351                 return_value = -1;
352                 goto cmp_out;
353         }
354         if (name == NULL) {
355                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,10,
356                     "Arg(name) is NULL pointer.");
357                 return_value = -1;
358                 goto cmp_out;
359         }
360
361         return_value = strcmp(sched->modname, name);
362
363 cmp_out:
364         /*-------- DEBUG LOG --------*/
365         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
366                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,18,
367                     "out_function: gint l7vs_sched_cmp(struct l7vs_scheduler* sched, char* name): "
368                     "return_value=%d", return_value);
369         }
370         /*------ DEBUG LOG END ------*/
371
372         return return_value;
373 }
374
375 /*!
376  * Sorry status of the specified service is checked.
377  * @param[in]   *srv            service pointer
378  * @param[in]   cc_check_flag   connection count check flag
379  * @return      int             check result 0=not sorry or check NG , 1=sorry
380  */
381 int
382 l7vs_sched_sorry_check(struct l7vs_service *srv, int cc_check_flag)
383 {
384         GList *l;
385         struct l7vs_dest *d;
386         int dest_cc = 0;
387         int return_value = 0;
388
389         /*-------- DEBUG LOG --------*/
390         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
391                 char srv_str[DEBUG_STR_LEN] = {0};
392                 l7vs_service_c_str(srv_str, srv);
393                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,19,
394                     "in_function: int l7vs_sched_sorry_check(struct l7vs_service* srv, int cc_check_flag): "
395                     "svc=&(%s), cc_check_flag=%d", srv_str, cc_check_flag);
396         }
397         /*------ DEBUG LOG END ------*/
398
399         // argument check
400         if (!srv) {
401                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,11,
402                     "Argument srv is NULL pointer");
403                 goto sorry_check_out;
404         }
405         if (cc_check_flag != 0 && cc_check_flag != 1) {
406                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,12,
407                     "Invalid cc_check_flag value");
408                 goto sorry_check_out;
409         }
410
411         // check sorry-flag of service
412         if (srv->sorry_flag) {
413                 return_value = 1;
414                 goto sorry_check_out;
415         }
416
417         // check valid destination of service
418         if (!srv->dest_list) {
419                 return_value = 1;
420                 goto sorry_check_out;
421         }
422
423         // not continuous check if cc_check_flag==0
424         if (!cc_check_flag) {
425                 goto sorry_check_out;
426         }
427
428         // srv->sorry_cc not set then not sorry
429         if (srv->sorry_cc == 0) {
430                 goto sorry_check_out;
431         }
432         // check connection count in all real servers of service
433         for (l = g_list_first(srv->dest_list); l != NULL; l = g_list_next(l)) {
434                 d = (struct l7vs_dest *)l->data;
435                 if (d) {
436                         dest_cc += d->nactive;
437                         if (dest_cc + 1 > srv->sorry_cc) {
438                                 return_value = 1;
439                                 goto sorry_check_out;
440                         }
441                 }
442         }
443
444 sorry_check_out:
445         /*-------- DEBUG LOG --------*/
446         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
447                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,20,
448                     "out_function: int l7vs_sched_sorry_check(struct l7vs_service* srv, int cc_check_flag): "
449                     "return_value=%d", return_value);
450         }
451         /*------ DEBUG LOG END ------*/
452
453         return return_value;
454 }
455
456 /*!
457  * Get sorry-server destination or old real-server destination.
458  * @param[in]   *srv            service pointer
459  * @param[in]   *conn           connection pointer
460  * @param[in]   reverse         specification which get sorry-server or old real-server
461  * @return      l7vs_dest*      sorry-server or old real-server destination
462  */
463 struct l7vs_dest *
464 l7vs_sched_sorry_dest(struct l7vs_service *srv, struct l7vs_conn *conn, int reverse)
465 {
466         struct l7vs_dest* dest = NULL;
467
468         /*-------- DEBUG LOG --------*/
469         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
470                 char srv_str[DEBUG_STR_LEN] = {0};
471                 char conn_str[DEBUG_STR_LEN] = {0};
472                 l7vs_service_c_str(srv_str, srv);
473                 l7vs_conn_c_str(conn_str, conn);
474                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,21,
475                     "in_function: struct l7vs_dest* l7vs_sched_sorry_dest(struct l7vs_service* srv, "
476                     "struct l7vs_conn* conn, int reverse): srv=&(%s), conn=&(%s), reverse=%d",
477                     srv_str, conn_str, reverse);
478         }
479         /*------ DEBUG LOG END ------*/
480
481         // argument check
482         if (reverse != 0 && reverse != 1) {
483                 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,13,"Invalid reverse value");
484                 goto sorry_dest_out;
485         }
486         if (!reverse) {
487                 // argument check
488                 if (!srv) {
489                         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,14,"Argument srv is NULL pointer");
490                         goto sorry_dest_out;
491                 }
492                 // return sorry-server destination
493                 dest = srv->sorry_dest;
494         } else {
495                 // argument check
496                 if (!conn) {
497                         LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,15,"Argument srv is NULL pointer");
498                         goto sorry_dest_out;
499                 }
500                 // return old real-server destination
501                 dest = conn->old_dest;
502         }
503
504 sorry_dest_out:
505
506         if( dest ){
507                 char dest_str[DEBUG_STR_LEN] = {0};
508                 l7vs_dest_c_str(dest_str, dest);
509                 LOGGER_PUT_LOG_INFO(LOG_CAT_L7VSD_SORRY_SERVER,1, "SorryServer Information : %s",dest_str);
510         }
511
512         /*-------- DEBUG LOG --------*/
513         if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_SCHEDULE ) ){
514                 char dest_str[DEBUG_STR_LEN] = {0};
515                 l7vs_dest_c_str(dest_str, dest);
516                 LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_SCHEDULE,22,
517                     "out_function: struct l7vs_dest* l7vs_sched_sorry_dest(struct l7vs_service* srv, "
518                     "struct l7vs_conn* conn, int reverse): return_value=&(%s)", dest_str);
519         }
520         /*------ DEBUG LOG END ------*/
521
522
523         return dest;
524 }
525