OSDN Git Service

trunk整理
[ultramonkey-l7/ultramonkey-l7-v3.git] / l7vsd / src / l7vsd.cpp
1 /*!
2  *    @file    l7vsd.cpp
3  *    @brief    l7vsd main class
4  *
5  * L7VSD: Linux Virtual Server for Layer7 Load Balancing
6  * Copyright (C) 2009  NTT COMWARE Corporation.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  **********************************************************************/
24 #include <sys/mman.h>
25 #include <signal.h>
26 #include <pthread.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <sys/time.h>
30 #include <sys/resource.h>
31 #include <boost/shared_ptr.hpp>
32 #include <sched.h>
33
34 #include "l7vsd.h"
35 #include "error_code.h"
36 #include "snmpagent.h"
37 #include "snmpfunc.h"
38 #define    PARAM_SCHED_ALGORITHM    "task_scheduler_algorithm"
39 #define PARAM_SCHED_PRIORITY    "task_scheduler_priority"
40 #define TRAP_TIME_STRING_MAX_SIZE   (20)
41
42 namespace l7vs
43 {
44
45 //! constructor
46 l7vsd::l7vsd()
47         :    help(false),
48                          debug(false),
49              exit_requested(0),
50              received_sig(0)
51 {
52         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 1, "l7vsd::l7vsd", __FILE__, __LINE__);
53
54         option_dic["-h"]        = boost::bind(&l7vsd::parse_help, this, _1, _2, _3);
55         option_dic["--help"]    = boost::bind(&l7vsd::parse_help, this, _1, _2, _3);
56                 option_dic["-d"]                = boost::bind(&l7vsd::parse_debug, this, _1, _2, _3);
57                 option_dic["--debug"]   = boost::bind(&l7vsd::parse_debug, this, _1, _2, _3);
58
59         starttime = boost::posix_time::second_clock::local_time();
60 }
61
62 //! destructor
63 l7vsd::~l7vsd()
64 {
65         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 2, "l7vsd::~l7vsd", __FILE__, __LINE__);
66 }
67
68 //! virtual_service list command
69 //! @param[out]    array of vs_element
70 //! @param[out]    error_code
71 void    l7vsd::list_virtual_service(vselist_type *out_vslist, error_code &err)
72 {
73         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 3, "l7vsd::list_virtual_service", __FILE__, __LINE__);
74
75         boost::mutex::scoped_lock command_lock(command_mutex);
76         boost::mutex::scoped_lock vslist_lock(vslist_mutex);
77
78         if (!out_vslist) {
79                 std::string msg("out_vslist pointer is null.");
80                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 1, msg, __FILE__, __LINE__);
81                 err.setter(true, msg);
82                 return;
83         }
84
85         // make vselement list
86         for (vslist_type::iterator itr = vslist.begin();
87              itr != vslist.end();
88              ++itr) {
89                 out_vslist->push_back((*itr)->get_element());
90         }
91
92         /*-------- DEBUG LOG --------*/
93         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
94                 std::stringstream    debugstr;
95                 debugstr << "l7vsd::list_virtual_service return value:";
96                 unsigned int i = 0;
97                 BOOST_FOREACH(virtualservice_element vs_elem, *out_vslist) {
98                         debugstr << boost::format("*out_vslist[%d]=") % i;
99                         debugstr << vs_elem;
100                         debugstr << ": ";
101                         ++i;
102                 }
103                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 4, debugstr.str(), __FILE__, __LINE__);
104         }
105         /*------ DEBUG LOG END ------*/
106
107 }
108
109 //! virtual_service list verbose command
110 //! @param[out]    array of vs_element
111 //! @param[out]    error_code
112 void    l7vsd::list_virtual_service_verbose(l7vsd_response *response, error_code &err)
113 {
114         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 5, "l7vsd::list_virtual_service_verbose", __FILE__, __LINE__);
115
116         boost::mutex::scoped_lock command_lock(command_mutex);
117         boost::mutex::scoped_lock vslist_lock(vslist_mutex);
118
119         if (!response) {
120                 std::string msg("response pointer is null.");
121                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 2, msg, __FILE__, __LINE__);
122                 err.setter(true, msg);
123                 return;
124         }
125
126         if (!rep) {
127                 std::string msg("rep pointer is null.");
128                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 4, msg, __FILE__, __LINE__);
129                 err.setter(true, msg);
130                 return;
131         }
132
133         unsigned long long    total_client_recv_byte = 0ULL;
134         unsigned long long    total_client_send_byte = 0ULL;
135         unsigned long long    total_realserver_recv_byte = 0ULL;
136         unsigned long long    total_realserver_send_byte = 0ULL;
137
138         // make vselement list
139         for (vslist_type::iterator itr = vslist.begin();
140              itr != vslist.end();
141              ++itr) {
142                 response->virtualservice_status_list.push_back((*itr)->get_element());
143                 // calc send recv bytes
144                 total_client_recv_byte += (*itr)->get_up_recv_size();
145                 total_client_send_byte += (*itr)->get_down_send_size();
146                 total_realserver_recv_byte += (*itr)->get_down_recv_size();
147                 total_realserver_send_byte += (*itr)->get_up_send_size();
148         }
149
150         // get_replication_mode
151         response->replication_mode_status = rep->get_status();
152
153         // get all category log level
154         Logger::getLogLevelAll(response->log_status_list);
155
156     //get snmp info
157     response->snmpinfo = snmpagent::get_snmp_info();
158
159         // calc total bps
160         unsigned long long    total_bytes =
161                 total_client_recv_byte +
162                 total_client_send_byte +
163                 total_realserver_recv_byte +
164                 total_realserver_send_byte;
165
166         boost::posix_time::ptime    now =
167                 boost::posix_time::second_clock::local_time();
168         boost::posix_time::time_duration    dur = (now - starttime);
169         if (0ULL != dur.total_seconds())
170                 response->total_bps = (total_bytes / dur.total_seconds());
171         else
172                 response->total_bps = 0ULL;
173
174         response->total_client_recv_byte = total_client_recv_byte;
175         response->total_client_send_byte = total_client_send_byte;
176         response->total_realserver_recv_byte = total_realserver_recv_byte;
177         response->total_realserver_send_byte = total_realserver_send_byte;
178
179         /*-------- DEBUG LOG --------*/
180         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
181                 std::stringstream    debugstr;
182                 debugstr << boost::format("l7vsd::list_virtual_service_verbose return value:%s") % *response;
183                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 6, debugstr.str(), __FILE__, __LINE__);
184         }
185         /*------ DEBUG LOG END ------*/
186
187 }
188
189 //! virtual_service add command
190 //! @param[in]    vs_element
191 //! @param[out]    error_code
192 void    l7vsd::add_virtual_service(const virtualservice_element *in_vselement, error_code &err)
193 {
194         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 7, "l7vsd::add_virtual_service", __FILE__, __LINE__);
195
196         boost::mutex::scoped_lock command_lock(command_mutex);
197         boost::mutex::scoped_lock vslist_lock(vslist_mutex);
198
199         if (!in_vselement) {
200                 std::string msg("in_vselement pointer is null.");
201                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 5, msg, __FILE__, __LINE__);
202                 err.setter(true, msg);
203                 return;
204         }
205
206         /*-------- DEBUG LOG --------*/
207         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
208                 std::stringstream    debugstr;
209                 debugstr << "l7vsd::add_virtual_service arguments:";
210                 debugstr << boost::format("*in_vselement=%s") % *in_vselement;
211                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 8, debugstr.str(), __FILE__, __LINE__);
212         }
213         /*------ DEBUG LOG END ------*/
214
215         if (vslist.end() == search_vslist(*in_vselement)) {
216                 // replication null check
217                 if (NULL == rep) {
218                         std::string msg("replication pointer is null.");
219                         Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 6, msg, __FILE__, __LINE__);
220
221                         err.setter(true, msg);
222                         return;
223                 }
224                 // create virtualservice
225                 virtualservice_ptr    vsptr;
226                 try {
227                         vsptr.reset(new virtual_service(*this, *rep, *in_vselement));
228                 } catch (std::bad_alloc &) {
229                         std::string msg("virtualservice create failed.");
230                         Logger::putLogError(LOG_CAT_L7VSD_MAINTHREAD, 1, msg, __FILE__, __LINE__);
231                         err.setter(true, msg);
232                         return;
233                 }
234                 if (NULL == vsptr) {
235                         std::string msg("virtualservice pointer is null.");
236                         Logger::putLogError(LOG_CAT_L7VSD_MAINTHREAD, 2, msg, __FILE__, __LINE__);
237                         err.setter(true, msg);
238                         return;
239                 }
240
241                 // vs initialize
242                 vsptr->initialize(err);
243                 if (err)    return;
244
245                 // set virtualservice
246                 vsptr->set_virtualservice(*in_vselement, err);
247                 if (err)    return;
248
249                 try {
250
251                         // create thread and run
252                         vs_threads.create_thread(boost::bind(&virtual_service::run, vsptr));
253
254                 } catch (...) {
255                         std::stringstream    buf;
256                         buf << "virtualservice thread initialize failed.";
257                         Logger::putLogError(LOG_CAT_L7VSD_MAINTHREAD, 8, buf.str(), __FILE__, __LINE__);
258                         err.setter(true, buf.str());
259
260                         vsptr->stop();
261                         l7vs::error_code finalize_err;
262                         vsptr->finalize(finalize_err);
263
264                         /*-------- DEBUG LOG --------*/
265                         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
266                                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 41, "out l7vsd::add_virtual_service", __FILE__, __LINE__);
267                         }
268                         /*------ DEBUG LOG END ------*/
269
270                         return;
271                 }
272
273                 // add to vslist
274                 vslist.push_back(vsptr);
275
276                 //create trap message
277                 trapmessage trap_msg;
278                 trap_msg.type = trapmessage::VIRTUALSERVICE_ADD;
279
280                 std::ostringstream oss;
281                 oss << "TRAP00020001,A virtual service was added.vs:";
282                 if (in_vselement->udpmode) {
283                         if (in_vselement->udp_recv_endpoint.address().is_v6()) {
284                                 oss << "[" << in_vselement->udp_recv_endpoint.address().to_string() << "]:" << in_vselement->udp_recv_endpoint.port();
285                         } else {
286                                 oss << in_vselement->udp_recv_endpoint.address().to_string() << ":" << in_vselement->udp_recv_endpoint.port();
287                         }
288                 }
289                 else {
290                         if (in_vselement->tcp_accept_endpoint.address().is_v6()) {
291                                 oss << "[" << in_vselement->tcp_accept_endpoint.address().to_string() << "]:" << in_vselement->tcp_accept_endpoint.port();
292                         } else {
293                                 oss << in_vselement->tcp_accept_endpoint.address().to_string() << ":" << in_vselement->tcp_accept_endpoint.port();
294                         }
295                 }
296
297                 trap_msg.message = oss.str();
298
299                 error_code err_code;
300
301                 //push the trap message
302                 snmpagent::push_trapmessage(trap_msg, err_code);
303
304                 if (err_code) {
305                         std::string msg("Push trap message failed.");
306                         Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 124, msg, __FILE__, __LINE__);
307                 }
308
309                 // when first vs, replication switch to master
310                 if (1U == vslist.size()) {
311                         rep->switch_to_master();
312                 }
313         } else {
314                 std::string msg("virtual service already exist.");
315                 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 23, msg, __FILE__, __LINE__);
316
317                 err.setter(true, msg);
318                 return;
319         }
320 }
321
322 //! virtual_service del command
323 //! @param[in]    vs_element
324 //! @param[out]    error_code
325 void    l7vsd::del_virtual_service(const virtualservice_element *in_vselement, error_code &err)
326 {
327         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 9, "l7vsd::del_virtual_service", __FILE__, __LINE__);
328
329         boost::mutex::scoped_lock command_lock(command_mutex);
330         boost::mutex::scoped_lock vslist_lock(vslist_mutex);
331
332         if (!in_vselement) {
333                 std::string msg("in_vselement pointer is null.");
334                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 7, msg, __FILE__, __LINE__);
335                 err.setter(true, msg);
336                 return;
337         }
338
339         /*-------- DEBUG LOG --------*/
340         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
341                 std::stringstream    debugstr;
342                 debugstr << "l7vsd::del_virtual_service arguments:";
343                 debugstr << boost::format("*in_vselement=%s") % *in_vselement;
344                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 10, debugstr.str(), __FILE__, __LINE__);
345         }
346         /*------ DEBUG LOG END ------*/
347
348         vslist_type::iterator vsitr = search_vslist(*in_vselement , true);
349         if (vslist.end() !=  vsitr) {
350                 // vs stop
351                 (*vsitr)->stop();
352                 // vs finalize
353                 (*vsitr)->finalize(err);
354
355                 //create trap message
356                 trapmessage trap_msg;
357                 trap_msg.type = trapmessage::VIRTUALSERVICE_REMOVE;
358
359                 std::ostringstream oss;
360                 oss << "TRAP00020003,A virtual service was eliminated.vs:";
361                 if (in_vselement->udpmode) {
362                         if (in_vselement->udp_recv_endpoint.address().is_v6()) {
363                                 oss << "[" << in_vselement->udp_recv_endpoint.address().to_string() << "]:" << in_vselement->udp_recv_endpoint.port();
364                         } else {
365                                 oss << in_vselement->udp_recv_endpoint.address().to_string() << ":" << in_vselement->udp_recv_endpoint.port();
366                         }
367                 }
368                 else {
369                         if (in_vselement->tcp_accept_endpoint.address().is_v6()) {
370                                 oss << "[" << in_vselement->tcp_accept_endpoint.address().to_string() << "]:" << in_vselement->tcp_accept_endpoint.port();
371                         } else {
372                                 oss << in_vselement->tcp_accept_endpoint.address().to_string() << ":" << in_vselement->tcp_accept_endpoint.port();
373                         }
374                 }
375
376                 trap_msg.message = oss.str();
377
378                 error_code err_code;
379
380                 //push the trap message
381                 snmpagent::push_trapmessage(trap_msg, err_code);
382
383                 if (err_code) {
384                         std::string msg("Push trap message failed.");
385                         Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 125, msg, __FILE__, __LINE__);
386                 }
387
388                 // when first vs, replication switch to slave
389                 if (0U == vslist.size()) {
390                         rep->switch_to_slave();
391                 }
392         } else {
393                 std::string msg("virtual service not found.");
394                 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 24, msg, __FILE__, __LINE__);
395                 err.setter(true, msg);
396                 return;
397         }
398 }
399
400 //! virtual_service edit command
401 //! @param[in]    vs_element
402 //! @param[out]    error_code
403 void    l7vsd::edit_virtual_service(const virtualservice_element *in_vselement, error_code &err)
404 {
405         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 11, "l7vsd::edit_virtual_service", __FILE__, __LINE__);
406
407         boost::mutex::scoped_lock command_lock(command_mutex);
408         boost::mutex::scoped_lock vslist_lock(vslist_mutex);
409
410         if (!in_vselement) {
411                 std::string msg("in_vselement pointer is null.");
412                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 8, msg, __FILE__, __LINE__);
413                 err.setter(true, msg);
414                 return;
415         }
416
417         /*-------- DEBUG LOG --------*/
418         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
419                 std::stringstream    debugstr;
420                 debugstr << "l7vsd::edit_virtual_service arguments:";
421                 debugstr << boost::format("*in_vselement=%s") % *in_vselement;
422                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 12, debugstr.str(), __FILE__, __LINE__);
423         }
424         /*------ DEBUG LOG END ------*/
425
426         vslist_type::iterator vsitr = search_vslist(*in_vselement);
427         if (vslist.end() !=  vsitr) {
428                 // edit virtualservice
429                 (*vsitr)->edit_virtualservice(*in_vselement, err);
430                 if (err)    return;
431
432                 //create trap message
433                 trapmessage trap_msg;
434                 trap_msg.type = trapmessage::VIRTUALSERVICE_CHANGE;
435
436                 std::ostringstream oss;
437                 oss << "TRAP00020002,The virtual service was changed.vs:";
438                 if (in_vselement->udpmode) {
439                         if (in_vselement->udp_recv_endpoint.address().is_v6()) {
440                                 oss << "[" << in_vselement->udp_recv_endpoint.address().to_string() << "]:" << in_vselement->udp_recv_endpoint.port();
441                         } else {
442                                 oss << in_vselement->udp_recv_endpoint.address().to_string() << ":" << in_vselement->udp_recv_endpoint.port();
443                         }
444                 }
445                 else {
446                         if (in_vselement->tcp_accept_endpoint.address().is_v6()) {
447                                 oss << "[" << in_vselement->tcp_accept_endpoint.address().to_string() << "]:" << in_vselement->tcp_accept_endpoint.port();
448                         } else {
449                                 oss << in_vselement->tcp_accept_endpoint.address().to_string() << ":" << in_vselement->tcp_accept_endpoint.port();
450                         }
451                 }
452
453                 trap_msg.message = oss.str();
454
455                 error_code err_code;
456
457                 //push the trap message
458                 snmpagent::push_trapmessage(trap_msg, err_code);
459
460                 if (err_code) {
461                         std::string msg("Push trap message failed.");
462                         Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 126, msg, __FILE__, __LINE__);
463                 }                
464
465         } else {
466                 std::string msg("virtual service not found.");
467                 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 25, msg, __FILE__, __LINE__);
468
469                 err.setter(true, msg);
470                 return;
471         }
472 }
473
474 //! real_server add command
475 //! @param[in]    vs_element
476 //! @param[out]    error_code
477 void    l7vsd::add_real_server(const virtualservice_element *in_vselement, error_code &err)
478 {
479         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 13, "l7vsd::add_real_server", __FILE__, __LINE__);
480
481         boost::mutex::scoped_lock command_lock(command_mutex);
482         boost::mutex::scoped_lock vslist_lock(vslist_mutex);
483
484         if (!in_vselement) {
485                 std::string msg("in_vselement pointer is null.");
486                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 9, msg, __FILE__, __LINE__);
487                 err.setter(true, msg);
488                 return;
489         }
490
491         /*-------- DEBUG LOG --------*/
492         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
493                 std::stringstream    debugstr;
494                 debugstr << "l7vsd::add_real_server arguments:";
495                 debugstr << boost::format("*in_vselement=%s") % *in_vselement;
496                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 14, debugstr.str(), __FILE__, __LINE__);
497         }
498         /*------ DEBUG LOG END ------*/
499
500         vslist_type::iterator vsitr = search_vslist(*in_vselement);
501         if (vslist.end() !=  vsitr) {
502                 // add realserver
503                 (*vsitr)->add_realserver(*in_vselement, err);
504                 if (err)    return;
505
506                 //create trap message
507                 trapmessage trap_msg;
508                 trap_msg.type = trapmessage::REALSERVER_ADD;
509
510                 std::ostringstream oss;
511                 oss << "TRAP00020004,A real server was added.vs:";
512                 //virtualservice information
513                 if (in_vselement->udpmode) {
514                         if (in_vselement->udp_recv_endpoint.address().is_v6()) {
515                                 oss << "[" << in_vselement->udp_recv_endpoint.address().to_string() << "]:" << in_vselement->udp_recv_endpoint.port();
516                         } else {
517                                 oss << in_vselement->udp_recv_endpoint.address().to_string() << ":" << in_vselement->udp_recv_endpoint.port();
518                         }
519                 }
520                 else {
521                         if (in_vselement->tcp_accept_endpoint.address().is_v6()) {
522                                 oss << "[" << in_vselement->tcp_accept_endpoint.address().to_string() << "]:" << in_vselement->tcp_accept_endpoint.port();
523                         } else {
524                                 oss << in_vselement->tcp_accept_endpoint.address().to_string() << ":" << in_vselement->tcp_accept_endpoint.port();
525                         }
526                 }
527
528                 //realserver information
529                 BOOST_FOREACH(realserver_element elem, in_vselement->realserver_vector) {
530                         if (in_vselement->udpmode) {
531                                 if (elem.udp_endpoint.address().is_v6()) {
532                                         oss << ",rs:[" << elem.udp_endpoint.address().to_string() << "]:" << elem.udp_endpoint.port();
533                                 } else {
534                                         oss << ",rs:"  << elem.udp_endpoint.address().to_string() << ":" << elem.udp_endpoint.port();
535                                 }
536                         }
537                         else {
538                                 if (elem.tcp_endpoint.address().is_v6()) {
539                                         oss << ",rs:[" << elem.tcp_endpoint.address().to_string() << "]:" << elem.tcp_endpoint.port();
540                                 } else {
541                                         oss << ",rs:"  << elem.tcp_endpoint.address().to_string() << ":" << elem.tcp_endpoint.port();
542                                 }
543                         }
544                 }
545
546                 trap_msg.message = oss.str();
547
548                 error_code err_code;
549
550                 //push the trap message
551                 snmpagent::push_trapmessage(trap_msg, err_code);
552
553                 if (err_code) {
554                         std::string msg("Push trap message failed.");
555                         Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 127, msg, __FILE__, __LINE__);
556                 }                
557
558
559         } else {
560                 std::string msg("virtual service not found.");
561                 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 26, msg, __FILE__, __LINE__);
562
563                 err.setter(true, msg);
564                 return;
565         }
566 }
567
568 //! real_server del command
569 //! @param[in]    vs_element
570 //! @param[out]    error_code
571 void    l7vsd::del_real_server(const virtualservice_element *in_vselement, error_code &err)
572 {
573         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 15, "l7vsd::del_real_server", __FILE__, __LINE__);
574
575         boost::mutex::scoped_lock command_lock(command_mutex);
576         boost::mutex::scoped_lock vslist_lock(vslist_mutex);
577
578         if (!in_vselement) {
579                 std::string msg("in_vselement pointer is null.");
580                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 10, msg, __FILE__, __LINE__);
581                 err.setter(true, msg);
582                 return;
583         }
584
585         /*-------- DEBUG LOG --------*/
586         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
587                 std::stringstream    debugstr;
588                 debugstr << "l7vsd::del_real_server arguments:";
589                 debugstr << boost::format("*in_vselement=%s") % *in_vselement;
590                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 16, debugstr.str(), __FILE__, __LINE__);
591         }
592         /*------ DEBUG LOG END ------*/
593
594         vslist_type::iterator vsitr = search_vslist(*in_vselement);
595         if (vslist.end() !=  vsitr) {
596                 // del realserver
597                 (*vsitr)->del_realserver(*in_vselement, err);
598                 if (err)    return;
599
600                 //create trap message
601                 trapmessage trap_msg;
602                 trap_msg.type = trapmessage::REALSERVER_REMOVE;
603
604                 std::ostringstream oss;
605                 oss << "TRAP00020006,A real server was eliminated.vs:";
606                 //virtualservice information
607                 if (in_vselement->udpmode) {
608                         if (in_vselement->udp_recv_endpoint.address().is_v6()) {
609                                 oss << "[" << in_vselement->udp_recv_endpoint.address().to_string() << "]:" << in_vselement->udp_recv_endpoint.port();
610                         } else {
611                                 oss << in_vselement->udp_recv_endpoint.address().to_string() << ":" << in_vselement->udp_recv_endpoint.port();
612                         }
613                 }
614                 else {
615                         if (in_vselement->tcp_accept_endpoint.address().is_v6()) {
616                                 oss << "[" << in_vselement->tcp_accept_endpoint.address().to_string() << "]:" << in_vselement->tcp_accept_endpoint.port();
617                         } else {
618                                 oss << in_vselement->tcp_accept_endpoint.address().to_string() << ":" << in_vselement->tcp_accept_endpoint.port();
619                         }
620                 }
621
622                 //realserver information
623                 BOOST_FOREACH(realserver_element elem, in_vselement->realserver_vector) {
624                         if (in_vselement->udpmode) {
625                                 if (elem.udp_endpoint.address().is_v6()) {
626                                         oss << ",rs:[" << elem.udp_endpoint.address().to_string() << "]:" << elem.udp_endpoint.port();
627                                 } else {
628                                         oss << ",rs:"  << elem.udp_endpoint.address().to_string() << ":" << elem.udp_endpoint.port();
629                                 }
630                         }
631                         else {
632                                 if (elem.tcp_endpoint.address().is_v6()) {
633                                         oss << ",rs:[" << elem.tcp_endpoint.address().to_string() << "]:" << elem.tcp_endpoint.port();
634                                 } else {
635                                         oss << ",rs:"  << elem.tcp_endpoint.address().to_string() << ":" << elem.tcp_endpoint.port();
636                                 }
637                         }
638                 }
639
640                 trap_msg.message = oss.str();
641
642                 error_code err_code;
643
644                 //push the trap message
645                 snmpagent::push_trapmessage(trap_msg, err_code);
646
647                 if (err_code) {
648                         std::string msg("Push trap message failed.");
649                         Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 128, msg, __FILE__, __LINE__);
650                 }
651         } else {
652                 std::string msg("virtual service not found.");
653                 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 27, msg, __FILE__, __LINE__);
654
655                 err.setter(true, msg);
656                 return;
657         }
658 }
659
660 //! real_server edit command
661 //! @param[in]    vs_element
662 //! @param[out]    error_code
663 void    l7vsd::edit_real_server(const virtualservice_element *in_vselement, error_code &err)
664 {
665         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 17, "l7vsd::edit_real_server", __FILE__, __LINE__);
666
667         boost::mutex::scoped_lock command_lock(command_mutex);
668         boost::mutex::scoped_lock vslist_lock(vslist_mutex);
669
670         if (!in_vselement) {
671                 std::string msg("in_vselement pointer is null.");
672                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 11, msg, __FILE__, __LINE__);
673                 err.setter(true, msg);
674                 return;
675         }
676
677         /*-------- DEBUG LOG --------*/
678         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
679                 std::stringstream    debugstr;
680                 debugstr << "l7vsd::edit_real_server arguments:";
681                 debugstr << boost::format("*in_vselement=%s") % *in_vselement;
682                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 18, debugstr.str(), __FILE__, __LINE__);
683         }
684         /*------ DEBUG LOG END ------*/
685
686         vslist_type::iterator vsitr = search_vslist(*in_vselement);
687         if (vslist.end() !=  vsitr) {
688                 // del realserver
689                 (*vsitr)->edit_realserver(*in_vselement, err);
690                 if (err)    return;
691
692                 //create trap message
693                 trapmessage trap_msg;
694                 trap_msg.type = trapmessage::REALSERVER_CHANGE;
695
696                 std::ostringstream oss;
697                 oss << "TRAP00020005,The real server was changed.vs:";
698                 //virtualservice information
699                 if (in_vselement->udpmode) {
700                         if (in_vselement->udp_recv_endpoint.address().is_v6()) {
701                                 oss << "[" << in_vselement->udp_recv_endpoint.address().to_string() << "]:" << in_vselement->udp_recv_endpoint.port();
702                         } else {
703                                 oss << in_vselement->udp_recv_endpoint.address().to_string() << ":" << in_vselement->udp_recv_endpoint.port();
704                         }
705                 }
706                 else {
707                         if (in_vselement->tcp_accept_endpoint.address().is_v6()) {
708                                 oss << "[" << in_vselement->tcp_accept_endpoint.address().to_string() << "]:" << in_vselement->tcp_accept_endpoint.port();
709                         } else {
710                                 oss << in_vselement->tcp_accept_endpoint.address().to_string() << ":" << in_vselement->tcp_accept_endpoint.port();
711                         }
712                 }
713
714                 //realserver information
715                 BOOST_FOREACH(realserver_element elem, in_vselement->realserver_vector) {
716                         if (in_vselement->udpmode) {
717                                 if (elem.udp_endpoint.address().is_v6()) {
718                                         oss << ",rs:[" << elem.udp_endpoint.address().to_string() << "]:" << elem.udp_endpoint.port();
719                                 } else {
720                                         oss << ",rs:"  << elem.udp_endpoint.address().to_string() << ":" << elem.udp_endpoint.port();
721                                 }
722                         }
723                         else {
724                                 if (elem.tcp_endpoint.address().is_v6()) {
725                                         oss << ",rs:[" << elem.tcp_endpoint.address().to_string() << "]:" << elem.tcp_endpoint.port();
726                                 } else {
727                                         oss << ",rs:"  << elem.tcp_endpoint.address().to_string() << ":" << elem.tcp_endpoint.port();
728                                 }
729                         }
730                 }
731
732                 trap_msg.message = oss.str();
733
734                 error_code err_code;
735
736                 //push the trap message
737                 snmpagent::push_trapmessage(trap_msg, err_code);
738
739                 if (err_code) {
740                         std::string msg("Push trap message failed.");
741                         Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 129, msg, __FILE__, __LINE__);
742                 }
743
744
745         } else {
746                 std::string msg("virtual service not found.");
747                 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 28, msg, __FILE__, __LINE__);
748
749                 err.setter(true, msg);
750                 return;
751         }
752 }
753
754 //! virtual_service flush command
755 //! @param[out]    error_code
756 void    l7vsd::flush_virtual_service(error_code &err)
757 {
758         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 19, "l7vsd::flush_virtual_service", __FILE__, __LINE__);
759
760         boost::mutex::scoped_lock command_lock(command_mutex);
761         boost::mutex::scoped_lock vslist_lock(vslist_mutex);
762
763         // all virtualservice stop and finalize
764         for (;;) {
765                 vslist_type::iterator itr = vslist.begin();
766                 if (vslist.end() == itr) {
767                         break;
768                 } else {
769                         //create trap message
770                         trapmessage trap_msg;
771                         trap_msg.type = trapmessage::VIRTUALSERVICE_REMOVE;
772
773                         std::ostringstream oss;
774                         oss << "TRAP00020003,A virtual service was eliminated.vs:";
775                         if ((*itr)->get_element().udpmode) {
776                                 if ((*itr)->get_element().udp_recv_endpoint.address().is_v6()) {
777                                         oss << "[" << (*itr)->get_element().udp_recv_endpoint.address().to_string() << "]:" << (*itr)->get_element().udp_recv_endpoint.port();
778                                 } else {
779                                         oss << (*itr)->get_element().udp_recv_endpoint.address().to_string() << ":" << (*itr)->get_element().udp_recv_endpoint.port();
780                                 }
781                         }
782                         else {
783                                 if ((*itr)->get_element().tcp_accept_endpoint.address().is_v6()) {
784                                         oss << "[" << (*itr)->get_element().tcp_accept_endpoint.address().to_string() << "]:" << (*itr)->get_element().tcp_accept_endpoint.port();
785                                 } else {
786                                         oss << (*itr)->get_element().tcp_accept_endpoint.address().to_string() << ":" << (*itr)->get_element().tcp_accept_endpoint.port();
787                                 }
788                         }
789
790                         trap_msg.message = oss.str();
791
792                         error_code err_code;
793
794                         //push the trap message
795                         snmpagent::push_trapmessage(trap_msg, err_code);
796
797                         if (err_code) {
798                                 std::string msg("Push trap message failed.");
799                                 Logger::putLogError(LOG_CAT_L7VSD_VIRTUALSERVICE, 130, msg, __FILE__, __LINE__);
800                         }
801
802                         // vs stop
803                         (*itr)->stop();
804                         // vs finalize
805                         (*itr)->finalize(err);
806                 }
807         }
808
809         // join virtualservice threads
810         vs_threads.join_all();
811
812         // replication switch to slave
813         rep->switch_to_slave();
814 }
815
816 //! replication command
817 //! @param[in]    replication command
818 //! @param[out]    error_code
819 void    l7vsd::replication_command(const l7vsadm_request::REPLICATION_COMMAND_TAG *cmd, error_code &err)
820 {
821         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 20, "l7vsd::replication_command", __FILE__, __LINE__);
822
823         boost::mutex::scoped_lock command_lock(command_mutex);
824         boost::mutex::scoped_lock vslist_lock(vslist_mutex);
825
826         if (!cmd) {
827                 std::string msg("cmd pointer is null.");
828                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 12, msg, __FILE__, __LINE__);
829                 err.setter(true, msg);
830                 return;
831         }
832         if (!rep) {
833                 std::string msg("rep pointer is null.");
834                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 13, msg, __FILE__, __LINE__);
835                 err.setter(true, msg);
836                 return;
837         }
838
839         /*-------- DEBUG LOG --------*/
840         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
841                 std::stringstream    debugstr;
842                 debugstr << "l7vsd::replication_command arguments:";
843                 debugstr << boost::format("*cmd=%d") % *cmd;
844                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 21, debugstr.str(), __FILE__, __LINE__);
845         }
846         /*------ DEBUG LOG END ------*/
847
848         switch (*cmd) {
849         case    l7vsadm_request::REP_START:
850                 rep->start();
851                 break;
852         case    l7vsadm_request::REP_STOP:
853                 rep->stop();
854                 break;
855         case    l7vsadm_request::REP_FORCE:
856                 rep->force_replicate();
857                 break;
858         case    l7vsadm_request::REP_DUMP:
859                 rep->dump_memory();
860                 break;
861         default:
862                 std::string msg("invalid replication command.");
863                 Logger::putLogError(LOG_CAT_L7VSD_REPLICATION, 38, msg, __FILE__, __LINE__);
864                 err.setter(true, msg);
865                 return;
866         }
867 }
868
869 //! loglevel set command
870 //! @param[in]    log category
871 //! @param[in]    log level
872 //! @param[out]    error_code
873 void    l7vsd::set_loglevel(const LOG_CATEGORY_TAG *cat, const LOG_LEVEL_TAG *level, error_code &err)
874 {
875         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 22, "l7vsd::set_loglevel", __FILE__, __LINE__);
876
877         boost::mutex::scoped_lock command_lock(command_mutex);
878         boost::mutex::scoped_lock vslist_lock(vslist_mutex);
879
880         if (!cat) {
881                 std::string msg("cat pointer is null.");
882                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 14, msg, __FILE__, __LINE__);
883                 err.setter(true, msg);
884                 return;
885         }
886         if (!level) {
887                 std::string msg("level pointer is null.");
888                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 15, msg, __FILE__, __LINE__);
889                 err.setter(true, msg);
890                 return;
891         }
892
893         /*-------- DEBUG LOG --------*/
894         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
895                 std::stringstream    debugstr;
896                 debugstr << "l7vsd::set_loglevel arguments:";
897                 debugstr << boost::format("*cat=%d, level=%d") % *cat % *level;
898                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 23, debugstr.str(), __FILE__, __LINE__);
899         }
900         /*------ DEBUG LOG END ------*/
901
902         if (LOG_CAT_END == *cat) {
903                 // set loglevel all
904                 if (!Logger::setLogLevelAll(*level)) {
905                         std::string msg("set loglevel all failed.");
906                         Logger::putLogError(LOG_CAT_L7VSD_LOGGER, 122, msg, __FILE__, __LINE__);
907                         err.setter(true, msg);
908                         return;
909                 }
910         } else {
911                 if (!Logger::setLogLevel(*cat, *level)) {
912                         std::string msg("set loglevel failed.");
913                         Logger::putLogError(LOG_CAT_L7VSD_LOGGER, 123, msg, __FILE__, __LINE__);
914                         err.setter(true, msg);
915                         return;
916                 }
917         }
918 }
919
920 //! reload parameter command
921 //! @param[in]    reload component
922 //! @param[out]    error_code
923 void    l7vsd::reload_parameter(const PARAMETER_COMPONENT_TAG *comp, error_code &err)
924 {
925         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 26, "l7vsd::reload_parameter", __FILE__, __LINE__);
926
927         boost::mutex::scoped_lock command_lock(command_mutex);
928         boost::mutex::scoped_lock vslist_lock(vslist_mutex);
929
930         if (!comp) {
931                 std::string msg("comp pointer is null.");
932                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 19, msg, __FILE__, __LINE__);
933                 err.setter(true, msg);
934                 return;
935         }
936         if (!rep) {
937                 std::string msg("rep pointer is null.");
938                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 20, msg, __FILE__, __LINE__);
939                 err.setter(true, msg);
940                 return;
941         }
942
943         /*-------- DEBUG LOG --------*/
944         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
945                 std::stringstream    debugstr;
946                 debugstr << "l7vsd::reload_parameter arguments:";
947                 debugstr << boost::format("*comp=%d") % *comp;
948                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 27, debugstr.str(), __FILE__, __LINE__);
949         }
950         /*------ DEBUG LOG END ------*/
951
952         Parameter    param;
953         Logger        logger_instance;
954
955         switch (*comp) {
956         case    PARAM_COMP_REPLICATION:
957                 if (param.read_file(*comp)) {
958                         rep->reset();
959                 } else {
960                         std::string msg("parameter reload failed.");
961                         Logger::putLogError(LOG_CAT_L7VSD_PARAMETER, 7, msg, __FILE__, __LINE__);
962                         err.setter(true, msg);
963                         return;
964                 }
965
966                 break;
967         case    PARAM_COMP_LOGGER:
968                 if (param.read_file(*comp)) {
969
970                         try {
971                                 logger_instance.loadConf();
972                         } catch (...) {
973                         }
974
975                 } else {
976                         std::string msg("parameter reload failed.");
977                         Logger::putLogError(LOG_CAT_L7VSD_PARAMETER, 7, msg, __FILE__, __LINE__);
978                         err.setter(true, msg);
979                         return;
980                 }
981
982                 break;
983         case    PARAM_COMP_ALL:
984                 if (!param.read_file(PARAM_COMP_REPLICATION)) {
985                         std::string msg("parameter reload failed.");
986                         Logger::putLogError(LOG_CAT_L7VSD_PARAMETER, 7, msg, __FILE__, __LINE__);
987                         err.setter(true, msg);
988                         return;
989                 }
990
991                 if (!param.read_file(PARAM_COMP_LOGGER)) {
992                         std::string msg("parameter reload failed.");
993                         Logger::putLogError(LOG_CAT_L7VSD_PARAMETER, 7, msg, __FILE__, __LINE__);
994                         err.setter(true, msg);
995                         return;
996                 }
997
998                 rep->reset();
999                 try {
1000                         logger_instance.loadConf();
1001                 } catch (...) {
1002                 }
1003
1004                 break;
1005         default:
1006                 std::string msg("parameter reload command not found.");
1007                 Logger::putLogWarn(LOG_CAT_L7VSD_PARAMETER, 1, msg, __FILE__, __LINE__);
1008                 err.setter(true, msg);
1009                 return;
1010         }
1011
1012
1013 }
1014 void    l7vsd::set_snmp_info(const snmp_info* info, error_code &err)
1015 {
1016         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 42, "l7vsd::set_snmp_info", __FILE__, __LINE__);
1017
1018         boost::mutex::scoped_lock command_lock(command_mutex);
1019
1020         if (!info) {
1021                 std::string msg("info pointer is null.");
1022                 Logger::putLogFatal(LOG_CAT_L7VSD_MAINTHREAD, 21, msg, __FILE__, __LINE__);
1023                 err.setter(true, msg);
1024                 return;
1025         }
1026
1027         /*-------- DEBUG LOG --------*/
1028         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
1029                 std::stringstream    debugstr;
1030                 debugstr << boost::format("info=%s") % *info;
1031                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 43, debugstr.str(), __FILE__, __LINE__);
1032         }
1033         /*------ DEBUG LOG END ------*/
1034
1035     if (info->option_set_flag & snmp_info::SNMP_ENABLE_OPTION_FLAG)
1036     {
1037         if(info->enabled) {
1038             snmpagent::enable();
1039         }
1040         else {
1041             snmpagent::disable();
1042         }
1043     }
1044
1045     if (info->option_set_flag & snmp_info::SNMP_LOGTRAP_OPTION_FLAG)
1046     {
1047         if(info->logtrap_enabled) {
1048             snmpagent::logtrap_enable();
1049         }
1050         else {
1051             snmpagent::logtrap_disable();
1052         }
1053     }
1054
1055     if (info->option_set_flag & snmp_info::SNMP_LOGTRAP_LEVEL_OPTION_FLAG)
1056     {
1057         snmpagent::set_logtrap_level(info->logtrap_level);
1058     }
1059
1060     if (info->option_set_flag & snmp_info::SNMP_INTERVAL_OPTION_FLAG)
1061     {
1062         snmpagent::set_interval(info->interval);
1063     }
1064
1065     if (info->option_set_flag & snmp_info::SNMP_REFRESH_OPTION_FLAG)
1066     {
1067         {
1068             boost::mutex::scoped_lock vslist_lock(vslist_mutex);
1069             virtualservice_element element;
1070             element.udpmode = false;
1071             element.tcp_accept_endpoint = info->vs_endpoint;
1072             element.protocol_module_name = info->protocol;
1073             vslist_type::iterator it = search_vslist(element, true);
1074             if (it == vslist.end())
1075             {
1076                 std::string msg("virtual service not found.");
1077                 Logger::putLogWarn(LOG_CAT_L7VSD_VIRTUALSERVICE, 29, msg, __FILE__, __LINE__);
1078
1079                 err.setter(true, msg);
1080                 return;
1081             }
1082         }
1083
1084         snmpagent::refresh_statistics(info->vs_endpoint, info->protocol);
1085     }
1086
1087     if (info->option_set_flag & snmp_info::SNMP_REFRESH_ALL_OPTION_FLAG)
1088     {
1089         snmpagent::refresh_all_statistics();
1090     }
1091
1092 }
1093
1094 //! vs_list search function
1095 //! @param[in]    vs_element
1096 //! @param[out]    error_code
1097 l7vsd::vslist_type::iterator    l7vsd::search_vslist(
1098         const virtualservice_element &in_vselement,
1099         bool find_module_name) const
1100 {
1101         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 28, "l7vsd::search_vslist", __FILE__, __LINE__);
1102
1103         /*-------- DEBUG LOG --------*/
1104         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
1105                 std::stringstream    debugstr;
1106                 debugstr << "l7vsd::search_vslist arguments:";
1107                 debugstr << boost::format("in_vselement=%s") % in_vselement;
1108                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 29, debugstr.str(), __FILE__, __LINE__);
1109         }
1110         /*------ DEBUG LOG END ------*/
1111
1112         for (vslist_type::iterator itr = vslist.begin();
1113              itr != vslist.end();
1114              ++itr) {
1115                 if (in_vselement.udpmode) {
1116                         if (((*itr)->get_element().udpmode) &&
1117                             ((*itr)->get_element().udp_recv_endpoint  == in_vselement.udp_recv_endpoint)) {
1118                                 if (find_module_name) {
1119                                         if ((*itr)->get_element().protocol_module_name ==  in_vselement.protocol_module_name) {
1120                                                 return itr;
1121                                         }
1122                                 } else {
1123                                         return itr;
1124                                 }
1125                         }
1126                 } else {
1127                         if ((!((*itr)->get_element().udpmode)) &&
1128                             ((*itr)->get_element().tcp_accept_endpoint == in_vselement.tcp_accept_endpoint)) {
1129                                 if (find_module_name) {
1130                                         if ((*itr)->get_element().protocol_module_name ==  in_vselement.protocol_module_name) {
1131                                                 return itr;
1132                                         }
1133                                 } else {
1134                                         return itr;
1135                                 }
1136                         }
1137                 }
1138         }
1139         return vslist.end();
1140 }
1141
1142 //! virtualservice release from vslist
1143 //! @param[in]    vs_element
1144 void    l7vsd::release_virtual_service(const virtualservice_element &in_vselement) const
1145 {
1146         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 30, "l7vsd::release_virtual_service", __FILE__, __LINE__);
1147
1148         /*-------- DEBUG LOG --------*/
1149         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_MAINTHREAD)) {
1150                 std::stringstream    debugstr;
1151                 debugstr << "l7vsd::release_virtual_service arguments:";
1152                 debugstr << boost::format("in_vselement=%s") % in_vselement;
1153                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 31, debugstr.str(), __FILE__, __LINE__);
1154         }
1155         /*------ DEBUG LOG END ------*/
1156
1157         vslist_type::iterator vsitr = search_vslist(in_vselement);
1158         if (vslist.end() !=  vsitr) {
1159                 // remove from vslist
1160                 vslist.remove(*vsitr);
1161         }
1162 }
1163 //! virtualservice_list getter
1164 //! @return    vslist
1165 l7vsd::vslist_type    &l7vsd::get_virtualservice_list()
1166 {
1167         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 32, "l7vsd::get_virtualservice_list", __FILE__, __LINE__);
1168
1169         return vslist;
1170 }
1171
1172 //! virtualservice_list mutex getter
1173 //! @return    vslist_mutex
1174 boost::mutex    &l7vsd::get_virtualservice_list_mutex()
1175 {
1176         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 33, "l7vsd::get_virtualservice_list_mutex", __FILE__, __LINE__);
1177
1178         return vslist_mutex;
1179 }
1180
1181 //! replication_ptr getter
1182 //! @return    replication_ptr
1183 replication::REPLICATION_MODE_TAG l7vsd::get_replication_state() const
1184 {
1185     return rep->get_status();
1186 }
1187
1188
1189 //! l7vsd run method
1190 //! @param[in]    argument count
1191 //! @param[in]    argument value
1192 int    l7vsd::run(int argc, char *argv[])
1193 {
1194         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 34, "l7vsd::run", __FILE__, __LINE__);
1195
1196         /*-------- DEBUG LOG --------*/
1197         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSADM_COMMON)) {
1198                 std::stringstream    debugstr;
1199                 debugstr << boost::format("l7vsd::run arguments:%s") % argument_debug_dump(argc, argv);
1200                 Logger::putLogDebug(LOG_CAT_L7VSD_MAINTHREAD, 35, debugstr.str(), __FILE__, __LINE__);
1201         }
1202         /*------ DEBUG LOG END ------*/
1203
1204         mlockall(MCL_FUTURE);
1205
1206         try {
1207                 // check options
1208                 if (!check_options(argc, argv)) {
1209                         std::cerr << usage();
1210                         munlockall();
1211                         return -1;
1212                 }
1213
1214                 // help mode ?
1215                 if (help) {
1216                         std::cout << usage();
1217                         munlockall();
1218                         return 0;
1219                 }
1220
1221                                 if( !debug ){
1222                         if (0 > daemon(0, 0)) {
1223                         std::stringstream buf;
1224                         buf << "daemon() failed: " << strerror(errno);
1225                         logger.putLogError(LOG_CAT_L7VSD_MAINTHREAD, 3, buf.str(), __FILE__, __LINE__);
1226                         munlockall();
1227                         return -1;
1228                         }
1229                                 }
1230
1231                 //set max file open num
1232                 Parameter    param;
1233                 error_code    err;
1234                 int    maxfileno = param.get_int(PARAM_COMP_L7VSD, "maxfileno", err);
1235                 if (err) {
1236                         logger.putLogWarn(LOG_CAT_L7VSD_MAINTHREAD, 1,
1237                                           "maxfileno parameter not found.", __FILE__, __LINE__);
1238                         maxfileno = 1024;
1239                 }
1240                 if (maxfileno < 32) {
1241                         logger.putLogWarn(LOG_CAT_L7VSD_MAINTHREAD, 10,
1242                                           "invalid parameter for maxfileno.", __FILE__, __LINE__);
1243                         maxfileno = 1024;
1244                 }
1245
1246                 //set process scheduler & priority
1247                 int    scheduler = SCHED_OTHER;
1248                 bool   change_scheduler = true;
1249                 int    int_val = param.get_int(PARAM_COMP_L7VSD, PARAM_SCHED_ALGORITHM, err);
1250                 if (err) {
1251                         change_scheduler = false;
1252                 }
1253                 if (change_scheduler) {
1254                         if ((SCHED_FIFO == int_val) || (SCHED_RR == int_val) || (SCHED_OTHER == int_val) || (SCHED_BATCH == int_val)) {
1255                                 scheduler = int_val;
1256                         } else {
1257                                 logger.putLogWarn(LOG_CAT_L7VSD_MAINTHREAD, 5, "invalid parameter for task scheduler algorithm.", __FILE__, __LINE__);
1258                         }
1259                         int    proc_pri  = param.get_int(PARAM_COMP_L7VSD, PARAM_SCHED_PRIORITY, err);
1260                         if (err) {
1261                                 logger.putLogWarn(LOG_CAT_L7VSD_MAINTHREAD, 6, "task scheduler priority parameter not found.", __FILE__, __LINE__);
1262                                 proc_pri  = sched_get_priority_min(scheduler);
1263                         } else {
1264                                 if ((SCHED_FIFO == scheduler) || (SCHED_RR == scheduler)) {
1265                                         if (proc_pri < 1 || 99 < proc_pri) {
1266                                                 logger.putLogWarn(LOG_CAT_L7VSD_MAINTHREAD, 7, "invalid parameter for task scheduler priority.", __FILE__, __LINE__);
1267                                                 proc_pri  = sched_get_priority_min(scheduler);
1268                                         }
1269                                 }
1270                                 if ((SCHED_OTHER == scheduler) || (SCHED_BATCH == scheduler)) {
1271                                         if (proc_pri != 0) {
1272                                                 logger.putLogWarn(LOG_CAT_L7VSD_MAINTHREAD, 8, "invalid parameter for task scheduler priority.", __FILE__, __LINE__);
1273                                                 proc_pri  = sched_get_priority_min(scheduler);
1274                                         }
1275                                 }
1276                         }
1277
1278                         sched_param        scheduler_param;
1279                         int    ret_val        = sched_getparam(0, &scheduler_param);
1280                         scheduler_param.__sched_priority    = proc_pri;
1281                         ret_val            = sched_setscheduler(0, scheduler, &scheduler_param);
1282                         if (ret_val != 0) {
1283                                 logger.putLogWarn(LOG_CAT_L7VSD_MAINTHREAD, 9, "task scheduler setting failed.", __FILE__, __LINE__);
1284                         }
1285                 }
1286
1287                 struct rlimit lim;
1288                 lim.rlim_cur = maxfileno;
1289                 lim.rlim_max = maxfileno;
1290                 int ret;
1291                 ret = setrlimit(RLIMIT_NOFILE, &lim);
1292                 if (0 != ret) {
1293                         std::stringstream buf;
1294                         buf << "setrlimit failed:" << errno;
1295                         logger.putLogWarn(LOG_CAT_L7VSD_MAINTHREAD, 2, buf.str(), __FILE__, __LINE__);
1296                 }
1297
1298                 // signal handler thread start
1299                 boost::thread    sigthread(boost::bind(&l7vsd::sig_exit_handler, this));
1300                 sigthread.detach();
1301
1302                 // protocol module control initialize
1303                 protocol_module_control::getInstance().initialize(L7VS_MODULE_PATH);
1304
1305                 // schedule module control initialize
1306                 schedule_module_control::getInstance().initialize(L7VS_MODULE_PATH);
1307
1308                 // receiver initialize
1309                 receiver.reset(new command_receiver(dispatcher, L7VS_CONFIG_SOCKNAME, *this));
1310                 if (NULL ==  receiver) {
1311                         logger.putLogError(LOG_CAT_L7VSD_MAINTHREAD, 4, "command receiver pointer null.", __FILE__, __LINE__);
1312                         munlockall();
1313                         return -1;
1314                 }
1315
1316                 // replication initialize
1317                 rep.reset(new replication());
1318                 if (NULL ==  rep) {
1319                         logger.putLogError(LOG_CAT_L7VSD_MAINTHREAD, 5, "replication pointer null.", __FILE__, __LINE__);
1320                         munlockall();
1321                         return -1;
1322                 }
1323                 if (0 > rep->initialize()) {
1324                         logger.putLogWarn(LOG_CAT_L7VSD_MAINTHREAD, 3, "replication initialize failed.", __FILE__, __LINE__);
1325                 }
1326
1327                 // snmpagent initialize
1328                 snmpagent agent(this);
1329
1330                 // snmp trap function set
1331                 Logger::set_snmp_send_trap_func( boost::bind( &snmpagent::push_trapmessage, _1, _2 ) );
1332
1333                 error_code err_code;
1334
1335                 // snmp start
1336                 agent.start(err_code);
1337
1338                 if (err_code) {
1339                         logger.putLogError(LOG_CAT_L7VSD_MAINTHREAD, 8, "snmp function start failed.", __FILE__, __LINE__);
1340                 }
1341
1342                 err_code.setter(false, "");
1343
1344                 //create trap message
1345                 trapmessage trap_msg;
1346                 trap_msg.type = trapmessage::SERVICE_START;
1347                 trap_msg.message = "TRAP00010001,l7vsd start.";
1348
1349                 //push the trap message
1350                 snmpagent::push_trapmessage(trap_msg, err_code);
1351
1352                 if (err_code) {
1353                         std::string msg("Push trap message failed.");
1354                         Logger::putLogError(LOG_CAT_L7VSD_MAINTHREAD, 9, msg, __FILE__, __LINE__);
1355                 }
1356
1357                 // main loop
1358                 for (;;) {
1359                         if (unlikely(exit_requested)) {
1360                                 std::stringstream buf;
1361                                 buf << boost::format("l7vsd signal(%d) received. exiting...") % received_sig;
1362                                 logger.putLogInfo(LOG_CAT_L7VSD_MAINTHREAD, 1, buf.str(), __FILE__, __LINE__);
1363                                 break;
1364                         }
1365                         dispatcher.poll();
1366                         timespec    wait_val;
1367                         wait_val.tv_sec        = 0;
1368                         wait_val.tv_nsec    = 1000000;
1369                         nanosleep(&wait_val, NULL);
1370                         boost::this_thread::yield();
1371                 }
1372
1373                 // snmp trap function unset
1374                 Logger::set_snmp_send_trap_func(NULL);
1375
1376                 // check snmp function enabled
1377                 if (snmpagent::get_snmp_info().enabled) {
1378                         // get local time string
1379                         char time_buf[TRAP_TIME_STRING_MAX_SIZE] = {0};
1380                         time_t now = time(NULL);
1381                         struct tm *t = localtime(&now);
1382                         if (t) strftime(time_buf, sizeof(time_buf), "%Y/%m/%d %H:%M:%S", t);
1383
1384                         // make trap message
1385                         std::stringstream   trap_buf;
1386                         trap_buf << time_buf << "," << "TRAP00010002,l7vsd stop.";
1387                         char buff[HOST_NAME_MAX] = {0};
1388                         gethostname(buff, HOST_NAME_MAX);
1389                         trap_buf << "," << buff;
1390                         // send trap message
1391                         trap_service_stop(trap_buf.str());
1392                 }
1393
1394                 // snmp agent finalize
1395                 agent.finalize();
1396
1397                 // replication finalize
1398                 rep->finalize();
1399
1400                 // schedule module control finalize
1401                 schedule_module_control::getInstance().finalize();
1402
1403                 // protocol module control finalize
1404                 protocol_module_control::getInstance().finalize();
1405         } catch (std::exception &e) {
1406                 std::stringstream    buf;
1407                 buf << "l7vsd run error:" << e.what();
1408                 logger.putLogError(LOG_CAT_L7VSD_MAINTHREAD, 7, buf.str(), __FILE__, __LINE__);
1409                 munlockall();
1410                 return -1;
1411         }
1412
1413         munlockall();
1414         return 0;
1415 }
1416
1417 //! argument dump for debug
1418 //! @param[in]    argument count
1419 //! @param[in]    argument value
1420 std::string    l7vsd::argument_debug_dump(int argc, char *argv[])
1421 {
1422         std::stringstream buf;
1423         if (!argv) {
1424                 buf << "argument=(null)";
1425         } else {
1426                 buf << boost::format("argument={argc=%d: ") % argc;
1427                 for (int i = 0; i < argc; ++i) {
1428                         buf << boost::format("argv[%d]=%s: ") % i % argv[i];
1429                 }
1430                 buf << "}";
1431         }
1432         return buf.str();
1433 }
1434
1435 //! command option check
1436 //! @param[in]    argument count
1437 //! @param[in]    argument value
1438 bool    l7vsd::check_options(int argc, char *argv[])
1439 {
1440         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 36, "l7vsd::check_options", __FILE__, __LINE__);
1441
1442         for (int pos = 1; pos < argc; ++pos) {    // check options.
1443                 parse_opt_map_type::iterator itr = option_dic.find(argv[pos]);
1444                 if (itr != option_dic.end()) {    // find option
1445                         if (!itr->second(pos, argc, argv)) {
1446                                 return false;    // option function execute.
1447                         }
1448                 } else { // don't find option function.
1449                         std::stringstream buf;
1450                         buf << "l7vsd: unknown option: " << argv[ pos ] << "\n";
1451                         std::cerr << buf.str();
1452                         return false;
1453                 }
1454         }
1455         return true;
1456 }
1457
1458 //! command help parse
1459 //! @param[in]    argument count
1460 //! @param[in]    argument value
1461 bool    l7vsd::parse_help(int &pos, int argc, char *argv[])
1462 {
1463         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 37, "l7vsd::parse_help", __FILE__, __LINE__);
1464
1465         help = true;        //help_mode flag on
1466         return true;
1467 }
1468
1469 //! command debug parse
1470 bool    l7vsd::parse_debug( int& pos, int argc, char* argv[] ){
1471                 Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 38, "l7vsd::parse_help", __FILE__, __LINE__);
1472                 debug = true;
1473                 return true;
1474 }
1475
1476 //! create usage string
1477 //! @return        usage string
1478 std::string    l7vsd::usage()
1479 {
1480         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 39, "l7vsd::usage", __FILE__, __LINE__);
1481
1482         std::stringstream    stream;
1483         stream <<
1484                "Usage: l7vsd [-h]\n"
1485                "   -h    --help         print this help messages and exit\n";
1486         return stream.str();
1487 }
1488
1489 //! signal handler function
1490 void    l7vsd::sig_exit_handler()
1491 {
1492         Logger    logger(LOG_CAT_L7VSD_MAINTHREAD, 40, "l7vsd::sig_exit_handler", __FILE__, __LINE__);
1493
1494         sigset_t    sigmask;
1495         sigemptyset(&sigmask);
1496         sigaddset(&sigmask, SIGHUP);
1497         sigaddset(&sigmask, SIGINT);
1498         sigaddset(&sigmask, SIGQUIT);
1499         sigaddset(&sigmask, SIGTERM);
1500         sigaddset(&sigmask, SIGPIPE);
1501
1502         int    sig;
1503         sigwait(&sigmask, &sig);
1504
1505         received_sig = sig;
1506         exit_requested = 1;
1507 }
1508
1509 };// namespace l7vsd
1510
1511 #ifndef    TEST_CASE
1512
1513 extern "C" int pthread_sigmask_non(int how, const sigset_t *newmask, sigset_t *old_mask)
1514 {
1515         return 0;
1516 }
1517 int pthread_sigmask(int, const sigset_t *, sigset_t *) __attribute__((weak, alias("pthread_sigmask_non")));
1518
1519
1520 //! main function
1521 int main(int argc, char *argv[])
1522 {
1523
1524         int ret = 0;
1525
1526         // signal block
1527         sigset_t    newmask;
1528         sigset_t    oldmask;
1529         sigfillset(&newmask);
1530         ret = sigprocmask(SIG_BLOCK, &newmask, &oldmask);
1531         if (0 != ret)
1532                 return ret;
1533
1534         try {
1535                 l7vs::Logger    logger_instance;
1536                 l7vs::Parameter    parameter_instance;
1537                 logger_instance.loadConf();
1538                 l7vs::logger_access_manager::getInstance().access_log_rotate_loadConf();
1539
1540                 l7vs::l7vsd vsd;
1541
1542                 ret =  vsd.run(argc, argv);
1543         } catch (...) {
1544                 return -1;
1545         }
1546
1547         // restore sigmask
1548         pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
1549
1550         return ret;
1551
1552 }
1553 #endif    //TEST_CASE