#include <boost/asio.hpp>

#include "tcp_session_stub.h"
#include "udp_session.h"
#include "l7vsd.h"
#include "data_buff_base.h"
#include "tcp_thread_message.h"
//#include "tcp_thread_message_que.h"
#include "tcp_data.h"
#include "tcp_socket.h"
#include "parameter.h"
#include "replication.h"
#include "protocol_module_control.h"
#include "schedule_module_control.h"
#include "error_code.h"
#include "stub.h"
#include "protocol_module_test1.h"
#include "schedule_module_test1.h"

#include "boost/test/unit_test.hpp"

l7vs::session_result_message    result;


// protocol_module_control　STUB code
l7vs::protocol_module_control    &l7vs::protocol_module_control::getInstance()
{
        static    protocol_module_control    instance;
        return    instance;
}
void    l7vs::protocol_module_control::initialize(const std::string &infile_path) {}
void    l7vs::protocol_module_control::finalize() {}
l7vs::protocol_module_base     *l7vs::protocol_module_control::load_module(const std::string &modulename)
{
        l7vs::protocol_module_base *return_value = NULL;

        if (!debugg_flug_struct::getInstance().pmcontrol_err_flag())
                return_value = new l7vs::protocol_module_test1();

        return return_value;
}
void    l7vs::protocol_module_control::unload_module(protocol_module_base *module_ptr)
{
        delete  module_ptr;
}

l7vs::schedule_module_control  &l7vs::schedule_module_control::getInstance()
{
        static  schedule_module_control instance;
        return  instance;
}
void    l7vs::schedule_module_control::initialize(const std::string &infile_path) {}
void    l7vs::schedule_module_control::finalize() {}
l7vs::schedule_module_base     *l7vs::schedule_module_control::load_module(const std::string &modulename)
{
        l7vs::schedule_module_base *return_value = NULL;

        if (!debugg_flug_struct::getInstance().smcontrol_err_flag())
                return_value = new schedule_module_test1;

        return return_value;
}

void    l7vs::schedule_module_control::unload_module(schedule_module_base *module_ptr)
{
        delete module_ptr;
}

/*
// parameter stub
l7vs::Parameter::Parameter(){}

l7vs::Parameter::~Parameter(){}

bool    l7vs::Parameter::read_file( const PARAMETER_COMPONENT_TAG in,const std::string& filename ){    return true; }

int        l7vs::Parameter::get_int(    const PARAMETER_COMPONENT_TAG in_tag,
                                    const std::string& in_str,
                                    error_code& err ){
    int    retval = 0;
    if( debugg_flug_struct::getInstance().param_exist_flag() ){
        retval = SESSION_POOL_NUM_PARAM;
    }else{
        err.setter( true, "not exist value." );
    }
    return retval;
}
bool l7vs::Parameter::init( const PARAMETER_COMPONENT_TAG in_tag, const std::string& data){

    return(true);
}
std::string        l7vs::Parameter::get_string(const PARAMETER_COMPONENT_TAG in_tag,
                                            const std::string& in_str,
                                            error_code& err){
    return "";
}


void l7vs::Parameter::get_multistring(const PARAMETER_COMPONENT_TAG,
                         const std::string&,
                         std::vector<std::string>&,
                         error_code& ){


}
*/
l7vs::Logger::Logger() :
        scopedLogCategory(LOG_CAT_L7VSD_LOGGER),
        scopedLogId(0),
        scopedLogMessage("Logger Constructor"),
        scopedLogFile(__FILE__),
        scopedLogLine(__LINE__) {}

l7vs::Logger::Logger(LOG_CATEGORY_TAG cat, const unsigned int id, const std::string &msg, const char *file, int line) :
        scopedLogCategory(cat),
        scopedLogId(id),
        scopedLogMessage(msg),
        scopedLogFile(file),
        scopedLogLine(line) {}

l7vs::Logger::~Logger() {}

void    l7vs::Logger::loadConf() {}

l7vs::LOG_LEVEL_TAG l7vs::Logger::getLogLevel(l7vs::LOG_CATEGORY_TAG)
{
        l7vs::LOG_LEVEL_TAG        ret_tag = l7vs::LOG_LV_DEBUG;
        return ret_tag;
}

bool    l7vs::Logger::setLogLevel(l7vs::LOG_CATEGORY_TAG cat, l7vs::LOG_LEVEL_TAG level)
{
        return true;
}

void    l7vs::Logger::putLogFatal(l7vs::LOG_CATEGORY_TAG, const unsigned int, const std::string &msg, const char *, int)
{
        //std::cout << "FATAL : " << msg << std::endl;
        BOOST_MESSAGE(boost::format("FATAL : %s") % msg);
}

void    l7vs::Logger::putLogError(l7vs::LOG_CATEGORY_TAG, const unsigned int, const std::string &msg, const char *, int)
{
        // std::cout << "ERROR : " << msg << std::endl;
        BOOST_MESSAGE(boost::format("ERROR : %s") % msg);
}

void    l7vs::Logger::putLogWarn(l7vs::LOG_CATEGORY_TAG, const unsigned int, const std::string &msg, const char *, int)
{
        //std::cout << "WARN  : " << msg << std::endl;
        BOOST_MESSAGE(boost::format("WARN : %s") % msg);
}

void    l7vs::Logger::putLogInfo(l7vs::LOG_CATEGORY_TAG, const unsigned int, const std::string &msg, const char *, int)
{
        //std::cout << "INFO  : " << msg << std::endl;
        BOOST_MESSAGE(boost::format("INFO : %s") % msg);
}

void    l7vs::Logger::putLogDebug(l7vs::LOG_CATEGORY_TAG, const unsigned int, const std::string &msg, const char *, int)
{
        //std::cout << "DEBUG : " << msg << std::endl;
        BOOST_MESSAGE(boost::format("DEBUG : %s") % msg);
}

l7vs::l7vsd::l7vsd() {}
l7vs::l7vsd::~l7vsd() {}
l7vs::l7vsd::vslist_type::iterator    l7vs::l7vsd::search_vslist(const virtualservice_element &, bool)    const
{
        return vslist.begin();
}

void    l7vs::l7vsd::release_virtual_service(const virtualservice_element &) const {}


int        l7vs::replication::initialize()
{
        return 0;
}
void    l7vs::replication::finalize() {}
void    l7vs::replication::switch_to_master() {}
void    l7vs::replication::switch_to_slave() {}
void    *l7vs::replication::pay_memory(const std::string &inid, unsigned int &outsize)
{
        void *retval = debugg_flug_struct::getInstance().get_rep_area();
        outsize = l7vs::virtualservice_base::MAX_REPLICATION_DATA_NUM;
        return retval;
}
void    l7vs::replication::dump_memory() {}
void    l7vs::replication::start() {}
void    l7vs::replication::stop() {}
void    l7vs::replication::force_replicate() {}
void    l7vs::replication::reset() {}
l7vs::replication::REPLICATION_MODE_TAG    l7vs::replication::get_status()
{
        l7vs::replication::REPLICATION_MODE_TAG    retmode = l7vs::replication::REPLICATION_OUT;
        return retmode;
}
int        l7vs::replication::handle_send()
{
        return 0;
}
void        l7vs::replication::handle_receive(const boost::system::error_code &err, size_t size)
{
}
int        l7vs::replication::lock(const std::string &inid)
{
        return 0;
}
int        l7vs::replication::unlock(const std::string &inid)
{
        return 0;
}
int        l7vs::replication::refer_lock_mutex(const std::string &inid, mutex_ptr &outmutex)
{
        return 0;
}

/*
l7vs::data_buff_base::data_buff_base(){}
l7vs::data_buff_base::~data_buff_base(){}
void    l7vs::data_buff_base::initialize(){}
std::size_t    l7vs::data_buff_base::get_size(){
    return send_size;
}
void    l7vs::data_buff_base::set_size(const std::size_t set_size){}
boost::array< char , MAX_BUFFER_SIZE>&    l7vs::data_buff_base::get_data(){
    return data;
}
void    l7vs::data_buff_base::set_data(const boost::array< char , MAX_BUFFER_SIZE>& data){}
void    l7vs::data_buff_base::set_send_size(const std::size_t set_size){}
std::size_t    l7vs::data_buff_base::get_send_size(){
    return send_size;
}
*/
l7vs::tcp_realserver_connect_socket_list::tcp_realserver_connect_socket_list() {}
l7vs::tcp_realserver_connect_socket_list::~tcp_realserver_connect_socket_list() {}
void    l7vs::tcp_realserver_connect_socket_list::push_back(list_element realserver_socket) {}
l7vs::tcp_realserver_connect_socket_list::list_element  l7vs::tcp_realserver_connect_socket_list::get_socket()
{
        l7vs::tcp_realserver_connect_socket_list::list_element  retval;
        return retval;
}
bool    l7vs::tcp_realserver_connect_socket_list::empty()
{
        return true;
}

//l7vs::tcp_thread_message::tcp_thread_message(){}
//l7vs::tcp_thread_message::~tcp_thread_message(){}

//l7vs::tcp_thread_message_que::tcp_thread_message_que(){}
//l7vs::tcp_thread_message_que::~tcp_thread_message_que(){}
//void  l7vs::tcp_thread_message_que::push(tcp_thread_message_ptr message){}
//l7vs::tcp_thread_message_que::tcp_thread_message_ptr  l7vs::tcp_thread_message_que::front(){
//      return message_que.front();
//}
//bool  l7vs::tcp_thread_message_que::empty(){
//      return true;
//}
//void  l7vs::tcp_thread_message_que::clear(){}

/*
l7vs::tcp_data::tcp_data(){}
l7vs::tcp_data::~tcp_data(){}
void    l7vs::tcp_data::initialize(){}
void    l7vs::tcp_data::set_endpoint(const boost::asio::ip::tcp::endpoint set_endpoint){}
boost::asio::ip::tcp::endpoint    l7vs::tcp_data::get_endpoint(){
    return endpoint_info;
}
*/


//l7vs::tcp_socket::tcp_socket(boost::asio::io_service& io, const tcp_socket_option_info set_option): my_socket(io), open_flag(false), opt_info(set_option){
//}

//l7vs::tcp_socket::tcp_socket(boost::asio::io_service& io) : my_socket( io ){}
//l7vs::tcp_socket::~tcp_socket(){}
//boost::asio::ip::tcp::socket& l7vs::tcp_socket::get_socket(){
//      return my_socket;
//}
bool    l7vs::tcp_socket::connect(const boost::asio::ip::tcp::endpoint connect_endpoint, boost::system::error_code &ec)
{
        return true;
}
bool    l7vs::tcp_socket::close(boost::system::error_code &ec)
{
        return true;
}
bool    l7vs::tcp_socket::set_non_blocking_mode(boost::system::error_code &ec)
{
        return true;
}
std::size_t             l7vs::tcp_socket::write_some(boost::asio::mutable_buffers_1 buffers, boost::system::error_code &ec)
{
        size_t  ret = 0;
        return ret;
}
std::size_t             l7vs::tcp_socket::read_some(boost::asio::mutable_buffers_1 buffers, boost::system::error_code &ec)
{
        size_t  ret = 0;
        return ret;
}




l7vs::tcp_session::tcp_session(virtualservice_tcp &vs,
                               boost::asio::io_service &session_io,
                               const tcp_socket_option_info set_option,
                               const boost::asio::ip::tcp::endpoint listen_endpoint,
                               const bool ssl_mode,
                               boost::asio::ssl::context &set_ssl_context,
                               const bool set_ssl_cache_flag,
                               const int set_ssl_handshake_time_out,
                               logger_implement_access *set_access_logger)
        :
        io(session_io),
        parent_service(vs),
        exit_flag(false),
        thread_state(0),
        protocol_module(NULL),
        session_pause_flag(false),
        client_socket(session_io, set_option),
        upstream_buffer_size(8192),
        downstream_buffer_size(8192),
        virtualservice_endpoint(listen_endpoint),
        access_log_flag(false),
        access_logger(set_access_logger),
        ssl_flag(ssl_mode),
        client_ssl_socket(session_io, set_ssl_context, set_option),
        ssl_context(set_ssl_context),
        ssl_cache_flag(set_ssl_cache_flag),
        ssl_handshake_timer_flag(false),
        ssl_handshake_time_out(set_ssl_handshake_time_out),
        ssl_handshake_time_out_flag(false),
        socket_opt_info(set_option),
        sorry_flag(false)
{

        exit_flag = false;
        session_pause_flag = false;
        BOOST_MESSAGE("SESSION:CREATE");
}

l7vs::tcp_session::~tcp_session(void) {}
l7vs::session_result_message l7vs::tcp_session::initialize(void)
{
        l7vs::session_result_message    result;
        result.flag = false;
        return result;
}


//l7vs::session_result_message l7vs::tcp_session::initialize(void){
//    return(result);
//}

boost::asio::ip::tcp::socket &l7vs::tcp_session::get_client_socket(void)
{
        return client_socket.get_socket();
}

ssl_socket &l7vs::tcp_session::get_client_ssl_socket()
{
        return client_ssl_socket.get_socket();
}

bool    l7vs::tcp_session::is_thread_wait(void)
{
        return true;
}

void    l7vs::tcp_session::set_virtual_service_message(const TCP_VIRTUAL_SERVICE_MESSAGE_TAG  message)
{
        switch (message) {
        case SORRY_STATE_ENABLE: {
                //boost::mutex::scoped_lock( exit_flag_update_mutex );
                //exit_flag = true;
                boost::mutex::scoped_lock(sorry_flag_update_mutex);
                sorry_flag = true;
        }
        break;
        case SORRY_STATE_DISABLE: {
                //boost::mutex::scoped_lock( exit_flag_update_mutex );
                //exit_flag = false;
                boost::mutex::scoped_lock(sorry_flag_update_mutex);
                sorry_flag = false;
        }
        break;
        case SESSION_END: {
                boost::mutex::scoped_lock(exit_flag_update_mutex);
                boost::mutex::scoped_lock(module_function_sorry_disable_mutex);
                exit_flag = true;
                session_pause_flag = true;
        }
        break;
        case SESSION_PAUSE_ON: {
                boost::mutex::scoped_lock(module_function_sorry_disable_mutex);
                session_pause_flag = true;
        }
        break;
        case SESSION_PAUSE_OFF: {
                boost::mutex::scoped_lock(module_function_sorry_disable_mutex);
                session_pause_flag = false;
        }
        break;
        case    ACCESS_LOG_ON: {
                std::cout << "set_virtual_service_message called : ACCESS_LOG_ON" << std::endl;
                break;
        }
        case    ACCESS_LOG_OFF: {
                std::cout << "set_virtual_service_message called : ACCESS_LOG_OFF" << std::endl;
                break;
        }


        }
}

void    l7vs::tcp_session::up_thread_run(void)
{
        size_t  count = 0;
        std::cout << "active session";
        std::cout << boost::this_thread::get_id() << std::endl;
        exit_flag = false;
        while (!exit_flag) {
                ++count;
                if (!debugg_flug_struct::getInstance().session_loop_flag() && (count > 30000))
                        break;
        }
        std::cout << "release session";
        parent_service.release_session(this);
}

void    l7vs::tcp_session::down_thread_run(void) {}

void    l7vs::tcp_session::thread_state_update(const std::bitset<TCP_SESSION_THREAD_STATE_BIT> thread_flag, const bool regist) {}
void    l7vs::tcp_session::up_thread_client_accept_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_client_receive(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_client_respond(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_client_respond_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_client_disconnect(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_client_disconnect_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_realserver_send(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_realserver_get_destination_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_realserver_connect(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_realserver_connect_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_realserver_connection_fail_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_realserver_disconnect(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_realserver_disconnect_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_all_realserver_disconnect(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_sorryserver_send(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_sorryserver_get_destination_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_sorryserver_connect(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_sorryserver_connect_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_sorryserver_connection_fail_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_sorryserver_disconnect(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_sorryserver_disconnect_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_sorry_enable_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_sorry_disable_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_sorryserver_mod_disconnect(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_exit(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::up_thread_all_socket_close(void) {}

void    l7vs::tcp_session::down_thread_realserver_receive(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_realserver_disconnect(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_realserver_disconnect_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_all_realserver_disconnect(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_client_connection_chk_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_client_respond_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_client_send(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_client_disconnect(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_client_disconnect_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_sorryserver_receive(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_sorryserver_disconnect(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_sorryserver_disconnect_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_sorry_enable_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_sorryserver_mod_disconnect(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_sorry_disable_event(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_exit(const TCP_PROCESS_TYPE_TAG process_type) {}
void    l7vs::tcp_session::down_thread_all_socket_close() {}

void    l7vs::tcp_session::up_thread_client_accept(const TCP_PROCESS_TYPE_TAG process_type) {}

void    l7vs::tcp_session::handle_ssl_handshake_timer(const boost::system::error_code &error) {}

bool    l7vs::tcp_session::ssl_clear_keep_cache(ssl_st *)
{
        return(true);
}

l7vs::udp_session::udp_session(virtualservice_udp &vs, boost::asio::io_service &session_io) :    io(session_io),
        parent_service(vs),
        client_side_socket(io) {}
l7vs::udp_session::~udp_session() {}
l7vs::session_result_message    l7vs::udp_session::initialize(const udp_endpoint listen_end)
{
        l7vs::session_result_message    result;
        return result;
}

void    l7vs::udp_session::set_virtual_service_message(const UDP_VIRTUAL_SERVICE_MESSAGE_TAG message) {}
void    l7vs::udp_session::run(void) {}
bool    l7vs::udp_session::client_send(const udp_endpoint client_endpoint, const udp_session_buff &data_buff, const std::size_t data_size, boost::system::error_code &ec)
{
        return true;
}
void    l7vs::udp_session::release_request(const boost::thread::id release_thread_id) {}

void    l7vs::udp_session::make_request_thread(const int max_count) {}
void    l7vs::udp_session::active_request_thread(const udp_endpoint client_endpoint , const udp_session_buff receive_data, const std::size_t receive_size) {}
void    l7vs::udp_session::all_active_request_stop(void) {}


void    l7vs::session_thread_control::start_thread()
{
}
void    l7vs::session_thread_control::upstream_run()
{
        state_tag       state;
        upthread_running_mutex.lock();
        {
                // get first state from class upstream state.
                rw_scoped_lock  upstate_lock(upthread_state_mutex);
                state = upthread_state; //thread local state is update.
        }
        for (;;) {      // thread loop
                if (state == WAIT) {     // after create or session end. this thread is pooling mode
                        boost::mutex::scoped_lock       lock(upthread_condition_mutex);
//                      upthread_condition.wait( lock );        // thread is condition wait.( start at notify_all() )
                        boost::xtime    wait;
                        boost::xtime_get(&wait, boost::TIME_UTC);
                        wait.sec += 1;
                        upthread_running_mutex.unlock();
                        upthread_condition.timed_wait(lock, wait);   // thread is condition wait( start at notify_all() )
                        upthread_running_mutex.lock();
                } else if (state == EXIT) { // this state is vitrualservice end. thread is finishing.
                        break;
                } else { //state RUNNING
                        session->up_thread_run();       //session upstream thread looping.
                        stopupstream();
                }
                rw_scoped_lock  upstate_lock(upthread_state_mutex);
                state = upthread_state; //thread local state is update.
        }
        upthread_running_mutex.unlock();
        boost::mutex::scoped_lock up_lk(upthread_joining_mutex);
        upthread_joining_condition.notify_all();
}

void    l7vs::session_thread_control::downstream_run()
{
        state_tag       state;
        downthread_running_mutex.lock();
        {
                rw_scoped_lock  downstate_lock(downthread_state_mutex);
                state = downthread_state;       //thread local state is update.
        }
        for (;;) {      //thread loop
                if (state == WAIT) {     //after create or session end. this thread is pooling mode
                        boost::mutex::scoped_lock       lock(downthread_condition_mutex);
//                      downthread_condition.wait( lock ); // thread is condition wait( start at notify_all() )
                        boost::xtime    wait;
                        boost::xtime_get(&wait, boost::TIME_UTC);
                        wait.sec += 1;
                        downthread_running_mutex.unlock();
                        downthread_condition.timed_wait(lock, wait);   // thread is condition wait( start at notify_all() )
                        downthread_running_mutex.lock();
                } else if (state == EXIT) { // this state is vitrualservice end. thread is finishing.
                        break;
                } else { //state RUNNING
                        session->down_thread_run();//session downstream thread looping.
                        stopdownstream();
                }
                rw_scoped_lock  downstate_lock(downthread_state_mutex);
                state = downthread_state;       // thread local sate is update.
        }
        downthread_running_mutex.unlock();
        boost::mutex::scoped_lock down_lk(downthread_joining_mutex);
        downthread_joining_condition.notify_all();
}

void    l7vs::session_thread_control::startupstream()
{
        boost::mutex::scoped_lock       lock(upthread_condition_mutex);          //upstream state lock
        if (upthread_state != EXIT) upthread_state = RUNNING;            // upthread state update.[RUNNING] -> alive mode
        upthread_condition.notify_all();                                                        // conditionwait upstreamthread is run.
}

void    l7vs::session_thread_control::stopupstream()
{
        boost::mutex::scoped_lock       lock(upthread_condition_mutex);          // upstream state lock
        if (upthread_state != EXIT) upthread_state = WAIT;                               // upthread state is update [WAIT] -> pooling mode
}

void    l7vs::session_thread_control::startdownstream()
{
        boost::mutex::scoped_lock       lock(downthread_condition_mutex);                // downstream state lock
        if (downthread_state != EXIT) downthread_state = RUNNING;                // downstream state is update [RUNNING] -> alive mode
        downthread_condition.notify_all();                                                              // condition wait thread is run.
}

void    l7vs::session_thread_control::stopdownstream()
{
        boost::mutex::scoped_lock       lock(downthread_condition_mutex);        // downstream state lock
        if (downthread_state != EXIT) downthread_state = WAIT;                   // downstream state is update [WAIT] -> pooling mode
}

void    l7vs::session_thread_control::join()
{

        boost::mutex::scoped_lock       up_lk(upthread_joining_mutex);
        boost::mutex::scoped_lock       down_lk(downthread_joining_mutex);

        {
                rw_scoped_lock  upstate_lock(upthread_state_mutex);
                upthread_state = EXIT;  //upstream state update [EXIT] -> thread exit mode
        }
        {
                boost::mutex::scoped_lock upthread_running_wait(upthread_running_mutex);
                upthread_condition.notify_all();        // conditionwait thread is run
        }

        {
                rw_scoped_lock  downstate_lock(downthread_state_mutex);
                downthread_state = EXIT;        //downstream state update [EXIT] -> thread exit mode
        }
        {
                boost::mutex::scoped_lock downthread_running_wait(downthread_running_mutex);
                downthread_condition.notify_all(); //condition wait thread is run.
        }
        upthread_joining_condition.wait(up_lk);
        downthread_joining_condition.wait(down_lk);
        if (LOG_LV_DEBUG == l7vs::Logger::getLogLevel(l7vs::LOG_CAT_L7VSD_VIRTUALSERVICE)) {
                boost::format fmt("out_function : void session_thread_control::stopd ownstream() : up_status = %d / down_status = %d");
                fmt % upthread_state % downthread_state;
                l7vs::Logger::putLogDebug(l7vs::LOG_CAT_L7VSD_VIRTUALSERVICE, 15, fmt.str(), __FILE__, __LINE__);
        }

}

boost::mutex   &l7vs::session_thread_control::get_upthread_mutex()
{
        return  upthread_running_mutex;
}

boost::mutex   &l7vs::session_thread_control::get_downthread_mutex()
{
        return  downthread_running_mutex;
}


