3 * @brief the framework module of scheduer
4 * @brief it proceeds common function of scheduler
6 * L7VSD: Linux Virtual Server for Layer7 Load Balancing
7 * Copyright (C) 2005 NTT COMWARE Corporation.
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.
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.
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
24 **********************************************************************/
27 #include <sys/types.h>
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"
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);
44 static GList *l7vs_sched_list = NULL;
47 * Get scheduler module.
48 * @param[in] *name scheduler module name
49 * @return struct l7vs_scheduler* OK=scheduler pointer, NG=NULL
51 struct l7vs_scheduler *
52 l7vs_sched_get(char *name)
54 struct l7vs_scheduler *sched = NULL;
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);
61 /*------ DEBUG LOG END ------*/
65 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,2,
66 "Scheduler module name is NULL");
69 sched = l7vs_sched_lookup(name);
71 sched = l7vs_sched_load(name);
73 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,3,
74 "Scheduler module not found maybe module problem)");
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);
88 /*------ DEBUG LOG END ------*/
94 * Put scheduler module.
95 * @param[in] *sched scheduler pointer
99 l7vs_sched_put(struct l7vs_scheduler *sched)
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);
106 /*------ DEBUG LOG END ------*/
110 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,4,
111 "Arg(sched) is NULL pointer.");
115 if (--sched->refcnt <= 0) {
116 l7vs_module_remove(&l7vs_sched_list, sched);
117 l7vs_sched_unload(sched);
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)");
126 /*------ DEBUG LOG END ------*/
131 * Bind scheduler module to service.
132 * @param[in] *sched scheduler pointer
133 * @param[in] *svc service pointer
137 l7vs_sched_bind(struct l7vs_scheduler *sched,
138 struct l7vs_service *svc)
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);
147 /*------ DEBUG LOG END ------*/
151 svc->scheduler = sched;
152 if (sched->bind != NULL) {
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)");
162 /*------ DEBUG LOG END ------*/
166 * Unbind scheduler module form service.
167 * @param[in] *sched scheduler pointer
168 * @param[in] *svc service pointer
172 l7vs_sched_unbind(struct l7vs_scheduler *sched,
173 struct l7vs_service *svc)
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);
182 /*------ DEBUG LOG END ------*/
186 svc->scheduler = NULL;
187 if (sched->unbind != NULL) {
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)");
197 /*------ DEBUG LOG END ------*/
201 * Load scheduler module.
202 * @param[in] *name scheduler module name
203 * @return struct l7vs_scheduler* OK=scheduler pointer, NG=NULL
205 static struct l7vs_scheduler *
206 l7vs_sched_load(char *name)
208 struct l7vs_scheduler *sched = NULL;
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);
215 /*------ DEBUG LOG END ------*/
219 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,5,
220 "Scheduler module name is NULL");
223 sched = (struct l7vs_scheduler *)l7vs_module_load(name, "sched");
225 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,6,
226 "Module load error.");
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;
236 l7vs_module_register(&l7vs_sched_list, sched);
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);
244 /*------ DEBUG LOG END ------*/
250 * Unload scheduler module.
251 * @param[in] *sched scheduler pointer
255 l7vs_sched_unload(struct l7vs_scheduler *sched)
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);
264 /*------ DEBUG LOG END ------*/
268 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,7,
269 "Arg(sched) is NULL pointer.");
277 l7vs_module_unload(h);
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)");
285 /*------ DEBUG LOG END ------*/
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
293 static struct l7vs_scheduler *
294 l7vs_sched_lookup(char *name)
296 struct l7vs_scheduler* sched = NULL;
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);
304 /*------ DEBUG LOG END ------*/
308 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,8,
309 "Scheduler module name is NULL");
313 sched = (struct l7vs_scheduler *) l7vs_module_lookup(l7vs_sched_list, name,
314 (GCompareFunc) l7vs_sched_cmp);
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);
323 /*------ DEBUG LOG END ------*/
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
335 l7vs_sched_cmp(struct l7vs_scheduler *sched, char *name)
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);
345 /*------ DEBUG LOG END ------*/
349 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,9,
350 "Arg(sched) is NULL pointer.");
355 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,10,
356 "Arg(name) is NULL pointer.");
361 return_value = strcmp(sched->modname, name);
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);
370 /*------ DEBUG LOG END ------*/
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
382 l7vs_sched_sorry_check(struct l7vs_service *srv, int cc_check_flag)
387 int return_value = 0;
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);
397 /*------ DEBUG LOG END ------*/
401 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,11,
402 "Argument srv is NULL pointer");
403 goto sorry_check_out;
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;
411 // check sorry-flag of service
412 if (srv->sorry_flag) {
414 goto sorry_check_out;
417 // check valid destination of service
418 if (!srv->dest_list) {
420 goto sorry_check_out;
423 // not continuous check if cc_check_flag==0
424 if (!cc_check_flag) {
425 goto sorry_check_out;
428 // srv->sorry_cc not set then not sorry
429 if (srv->sorry_cc == 0) {
430 goto sorry_check_out;
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;
436 dest_cc += d->nactive;
437 if (dest_cc + 1 > srv->sorry_cc) {
439 goto 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);
451 /*------ DEBUG LOG END ------*/
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
464 l7vs_sched_sorry_dest(struct l7vs_service *srv, struct l7vs_conn *conn, int reverse)
466 struct l7vs_dest* dest = NULL;
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);
479 /*------ DEBUG LOG END ------*/
482 if (reverse != 0 && reverse != 1) {
483 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,13,"Invalid reverse value");
489 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,14,"Argument srv is NULL pointer");
492 // return sorry-server destination
493 dest = srv->sorry_dest;
497 LOGGER_PUT_LOG_ERROR(LOG_CAT_L7VSD_SCHEDULE,15,"Argument srv is NULL pointer");
500 // return old real-server destination
501 dest = conn->old_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);
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);
520 /*------ DEBUG LOG END ------*/