OSDN Git Service

Initial commit from 2.1.2-1
[ultramonkey-l7/ultramonkey-l7-v2.git] / src / service.c
diff --git a/src/service.c b/src/service.c
new file mode 100644 (file)
index 0000000..92a0b1b
--- /dev/null
@@ -0,0 +1,1677 @@
+/*
+ * @file  service.c
+ * @brief The function  of l7vsd is managed. 
+ * @brief Two or more service takes charge of the 
+ * @brief function respectively. 
+ *
+ * L7VSD: Linux Virtual Server for Layer7 Load Balancing
+ * Copyright (C) 2005  NTT COMWARE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ **********************************************************************/
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <sys/time.h>
+#include "logger_wrapper.h"
+#include "l7vs_config.h"
+#include "l7vs_service.h"
+#include "l7vs_module.h"
+#include "l7vs_conn.h"
+#include "l7vs_dest.h"
+#include "l7vs_iomuxlist.h"
+#include "l7vs_lsock.h"
+#include "l7vs_sched.h"
+
+#define        SERVICE_REPLICATION_MAX_NUM     32
+
+//! service list pointer
+static GList * l7vs_service_list;
+
+//! service handle
+uint32_t service_handle_base = 0;
+
+//! remove_conn list pointer
+static GList * removeconn_list;
+
+//! replication component id
+#define REP_COMP_SV     "virtualservice"
+
+//! replication size
+static  unsigned int    rep_size_num;
+
+//! Replication data backup
+static  l7vs_service_repdata * rep_mirror;
+
+//static functions
+static void l7vs_service_put_service_arg(struct l7vs_service_arg_multi *);
+
+// throughput interval
+static int throughput_interval = 0;
+
+/*!
+ * make replication data from l7vs_service structure
+ * @param[in]   num     unsigned int/number of array(l7vs_service_repdata)
+ * @param[out] **rep_data      l7vs_service_repdata struct double-pointer
+ * @return      int     number currently created / -1 failure
+ */
+static int
+make_replication_data( unsigned int num, struct l7vs_service_repdata* rep_data )
+{
+       unsigned int loopcnt;
+       unsigned int listcnt;
+       struct  l7vs_service*   sv;
+       struct  l7vs_service_arg_multi* svmulti;
+
+       //argument check
+       if( 1 > num )return -1;
+       if( NULL == rep_data )return -1;
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function make_replication_data( unsigned int num, struct l7vs_service_repdata* rep_data )");
+               sprintf( debugstr, "%s num = %d", debugstr, num );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,5, debugstr );
+       }
+
+       loopcnt = num;
+       listcnt = g_list_length( l7vs_service_list );
+       if( 0 == listcnt )return -1;
+
+       if( loopcnt > listcnt )loopcnt = listcnt;
+       for( unsigned int i = 0; i < loopcnt; ++i ){
+               sv = (struct l7vs_service*)g_list_nth_data( l7vs_service_list, i );
+               if( NULL == sv ){
+                       loopcnt = i-1;
+                       break;
+               }
+               svmulti = l7vs_service_get_service_arg( sv );
+               if( NULL == svmulti )return -1;
+               rep_data[i].addr = svmulti->srv_arg.addr;
+               rep_data[i].proto       = svmulti->srv_arg.proto;
+               memcpy( rep_data[i].protomod, svmulti->srv_arg.protomod, L7VS_MODNAME_LEN );
+               memcpy( rep_data[i].protomod_arg, svmulti->protomod_arg, L7VS_PROTOMOD_MAX_SERVICE_ARG );
+               //Sorry server information
+               rep_data[i].sorry_cc    = svmulti->srv_arg.sorry_cc;
+               rep_data[i].sorry_addr  = svmulti->srv_arg.sorry_addr;
+               rep_data[i].sorry_flag  = svmulti->srv_arg.sorry_flag;
+               //QoS information
+               rep_data[i].qos_threshold_up   = svmulti->srv_arg.qos_threshold_up;
+               rep_data[i].qos_threshold_down = svmulti->srv_arg.qos_threshold_down;
+
+               l7vs_service_put_service_arg( svmulti );
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "rep_data[%d] dump", i);
+                       l7vs_service_repdata_c_str( debugstr, &rep_data[i] );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,6, debugstr );
+               }
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function make_replication_data( unsigned int num, struct l7vs_service_repdata* rep_data )");
+               sprintf( debugstr, "%s return(list num) = %d", debugstr, loopcnt );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,7, debugstr );
+       }
+       return  loopcnt;
+}
+
+/*!
+ *
+ */
+void
+set_replication_data( unsigned int num, struct l7vs_service_repdata* rep_data, l7vs_service * srv )
+{
+       struct  l7vs_lsock *    lsock;
+       struct  l7vs_protomod * pmod;
+       struct  l7vs_service *  s;
+       int     ret = 0;
+
+       //argument check
+       if( 0 == num )return;
+       if( NULL == rep_data )return;
+
+       for( unsigned int i = 0; i < num; ++i ){
+               //lsock lookup
+               lsock = l7vs_lsock_table_lookup( &rep_data[i].addr, rep_data[i].proto );
+               if( (NULL == lsock) || (lsock != srv->lsock) )continue;
+               //protomod lookup
+               pmod = l7vs_protomod_lookup( rep_data[i].protomod );
+               if( (NULL == pmod) || (pmod != srv->pm) )continue;
+               //
+               s = (struct l7vs_service *) calloc(1, sizeof(struct l7vs_service));
+               if (s == NULL) {
+                       LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM, 81, "l7vs_service memory allocate error" );
+                       return;
+               }
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "memory allocated : address = %p , size = %zu", s, sizeof(struct l7vs_service) );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE, 94, debugstr );
+               }
+               s->handle = TEMP_SERVICEHANDLE;
+               ret = pmod->create( rep_data[i].protomod_arg, s->handle );
+               if( (0 != ret) || (0 != pmod->compare(s->handle, srv->handle)) ){
+                       pmod->destroy(s->handle);
+                       free(s);
+                       continue;
+               }
+               pmod->destroy(s->handle);
+               free(s);
+               srv->sorry_cc   = rep_data[i].sorry_cc;
+               //if sorry is "NULL". Make a sorry_data.
+               if( NULL == srv->sorry_dest ){
+                       srv->sorry_dest = l7vs_dest_create( (struct sockaddr_in*)&rep_data[i].sorry_addr, 1 );
+               }else{
+                       memcpy( (void*)&srv->sorry_dest->addr, (void*)&rep_data[i].sorry_addr, sizeof(struct sockaddr_in) );
+                       srv->sorry_dest->weight = 1;
+                       srv->sorry_flag = rep_data[i].sorry_flag;
+                       srv->qos_threshold_up   = rep_data[i].qos_threshold_up;
+                       srv->qos_threshold_down = rep_data[i].qos_threshold_down;
+               }
+               break;
+       }
+}
+
+/*!
+ * l7vs_servcie_get_service_arg
+ * service arg pointer lookup.
+ * @param[in]  srv     l7vs_service pointer.
+ * @return     l7vs_service_arg_multi pointer
+ */
+struct l7vs_service_arg_multi *
+l7vs_service_get_service_arg(struct l7vs_service *srv)
+{
+        struct l7vs_service_arg_multi *sa;
+       int ret = 0;
+
+       if( NULL == srv ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,7, "argument srv is NULL");
+               return NULL;
+       }
+       if( NULL == srv->pm || NULL == srv->lsock || NULL == srv->scheduler ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,8, "Invalid argument" );
+               return NULL;
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_get_service_arg(struct l7vs_service *srv)");
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,8, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "srv dump" );
+               l7vs_service_c_str( debugstr, srv );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,9, debugstr );
+       }
+
+        sa = (struct l7vs_service_arg_multi *) calloc(1, sizeof(struct l7vs_service_arg_multi));
+        if (sa == NULL) {
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_SYSTEM_MEMORY,1, "Could not allocate memory" );
+                return NULL;
+        }
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "memory allocated : address = %p , size = %zu", sa, sizeof(struct l7vs_service_arg_multi) );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,10, debugstr );
+       }
+
+       ret = srv->pm->service_arg(sa, srv->handle);
+       if (ret == -1) {
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "memory free : address = %p", sa );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,11, debugstr );
+               }
+               free( sa );
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROTOCOL,1, "service not found" );
+               return NULL;
+       }
+
+       sa->srv_arg.len = sizeof(struct l7vs_service_arg_multi);
+        sa->srv_arg.addr = srv->lsock->addr;
+        sa->srv_arg.proto = srv->lsock->proto;
+        sa->srv_arg.persist = 0 /* XXX not yet */;
+        sa->srv_arg.backlog = 5 /* XXX not yet */;
+        strcpy(sa->srv_arg.protomod, srv->pm->modname);
+        strcpy(sa->srv_arg.schedmod, srv->scheduler->modname);
+
+       sa->srv_arg.sorry_cc    = srv->sorry_cc;
+       sa->srv_arg.sorry_flag  = srv->sorry_flag;
+       memcpy( &sa->srv_arg.sorry_addr, &srv->sorry_dest->addr, sizeof(struct sockaddr_in) );
+
+       sa->srv_arg.qos_threshold_up    = srv->qos_threshold_up;
+       sa->srv_arg.qos_threshold_down  = srv->qos_threshold_down;
+
+
+    struct timeval CurrTime;
+    gettimeofday( &CurrTime, NULL );
+    if (throughput_interval == 0) {
+        if ( parameter_is_int_exist( PARAM_COMP_L7VSD, "calc_throughput_interval" ) ) {
+            throughput_interval = parameter_get_int_value( PARAM_COMP_L7VSD, "calc_throughput_interval" );
+        }
+        if (throughput_interval == 0) {
+            throughput_interval = BPS_DEFAULT_INTERVAL;
+        }
+    }
+    unsigned long long cur_recvtime = (CurrTime.tv_sec * 1000000ULL + CurrTime.tv_usec) / throughput_interval;
+    l7vs_service_update_throughput(srv, cur_recvtime);
+    srv->throughput_to_server = srv->pre_recvsize_from_client * 1000000ULL / throughput_interval;
+    srv->throughput_to_client = srv->pre_recvsize_from_server * 1000000ULL / throughput_interval;
+
+
+       if (srv->qos_threshold_up != 0) {
+               srv->throughput_to_server >= srv->qos_threshold_up
+                               ? sa->srv_arg.throughput_to_server = srv->qos_threshold_up
+                               : sa->srv_arg.throughput_to_server = srv->throughput_to_server;
+       } else {
+               sa->srv_arg.throughput_to_server = srv->throughput_to_server;
+       }
+
+       if (srv->qos_threshold_down != 0) {
+               srv->throughput_to_client >= srv->qos_threshold_down
+                               ? sa->srv_arg.throughput_to_client = srv->qos_threshold_down
+                               : sa->srv_arg.throughput_to_client = srv->throughput_to_client;
+       } else {
+               sa->srv_arg.throughput_to_client = srv->throughput_to_client;
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "return value : l7vs_service_arg_multi dump" );
+               l7vs_service_arg_multi_c_str( debugstr, sa );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,12, debugstr );
+       }
+        return sa;
+}
+
+/*!
+ * service_arg destroy function.
+ * @param[in] sa       l7vs_service_arg pointer
+ */
+static void
+l7vs_service_put_service_arg(struct l7vs_service_arg_multi *sa)
+{
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_put_service_arg(struct l7vs_service_arg_multi *sa)");
+               sprintf( debugstr, "%s , sa free : address = %p", debugstr, sa );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,13, debugstr );
+       }
+        free(sa);
+}
+
+
+/*!
+ * Target real servers of sets of real servers in service are retrieved. 
+ * @param[in]  *srv    service pointer
+ * @param[in]  *sin    IP and port
+ * @return     l7vs_dest* real server struct pointer
+ */
+struct l7vs_dest *
+l7vs_service_lookup_dest(struct l7vs_service *srv,
+                         struct sockaddr_in *sin)
+{
+        GList *l;
+        struct l7vs_dest *d, *found;
+
+       if( NULL == srv ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,9, "lookup dest : argument \"srv\" is NULL" );
+               return NULL;
+       }
+       if( NULL == sin ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,10, "lookup dest : argument \"sin\" is NULL" );
+               return NULL;
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_lookup_dest(struct l7vs_service *srv, struct sockaddr_in *sin)" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,14, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "srv dump" );
+               l7vs_service_c_str( debugstr, srv );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,15, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "sin dump " );
+               switch( sin->sin_family ){
+               case AF_UNIX:
+                       sprintf( debugstr, "%s socket family = AF_UNIX(PF_UNIX)", debugstr );
+                       break;
+               case AF_INET:
+                       sprintf( debugstr, "%s socket family = AF_INET(PF_INET)", debugstr );
+                       break;
+               default:
+                       sprintf( debugstr, "%s socket family = %d", debugstr, sin->sin_family );
+               }
+               sprintf( debugstr, "%s port no = %d", debugstr, ntohs( sin->sin_port ) );
+               sprintf( debugstr, "%s address = %s", debugstr, inet_ntoa( sin->sin_addr ) );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,16, debugstr );
+       }
+
+        found = NULL;
+        for (l = g_list_first(srv->dest_list); l != NULL; l = g_list_next(l)) {
+                d = (struct l7vs_dest *)l->data;
+                if ((d->addr.sin_addr.s_addr == sin->sin_addr.s_addr) && (d->addr.sin_port == sin->sin_port)) {
+                        found = d;
+                        break;
+                }
+        }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "return value = %p", found );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,17, debugstr );
+       }
+
+        return found;
+}
+
+/*!
+ *
+ * @param[out] **sas   l7vs_service_arg pointer list
+ * @param[out] *num    pointer list count
+ * @return             pointer list count
+
+ */
+int
+l7vs_service_list_service_arg(struct l7vs_service_arg_multi **sas, int *num)
+{
+        GList *l;
+        struct l7vs_service *srv;
+        struct l7vs_service_arg_multi *r, *s;
+        struct l7vs_service_arg_multi **sa;
+        int i, n, len;
+
+       if( NULL == sas ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,11, "list service_arg : argument \"sas\" is NULL" );
+               return -1;
+       }
+       if( NULL == num ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,12, "list service_arg : argument \"num\" is NULL" );
+               return -1;
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_list_service_arg(struct l7vs_service_arg_multi **sas, int *num)" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,18, debugstr );
+       }
+
+        n = g_list_length(l7vs_service_list);
+        if (n == 0) {
+                *sas = NULL;
+                *num = 0;
+                return 0;
+        }
+
+        sa = (struct l7vs_service_arg_multi **)calloc(n, sizeof(*sa));
+       if (sa == NULL) {
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_SYSTEM_MEMORY,2, "list service_arg : Could not allocate memory" );
+               return -1;
+       }
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "memory allocated : address = %p , size = %zu", sa, sizeof(struct l7vs_service_arg_multi) );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,19, debugstr );
+       }
+
+        len = 0;
+        l = g_list_first(l7vs_service_list);
+        for (i = 0; i < n; i++) {
+                srv = (struct l7vs_service *)l->data;
+                sa[i] = l7vs_service_get_service_arg(srv);
+                if (sa[i] == NULL) {
+                        for (i-- ; i >= 0; i--) {
+                                l7vs_service_put_service_arg(sa[i]);
+                        }
+                       //DEBUG output
+                       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                               char    debugstr[DEBUG_STR_LEN];
+                               memset( debugstr, 0, DEBUG_STR_LEN );
+                               sprintf( debugstr, "memory free : address = %p", sa );
+                               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,20, debugstr );
+                       }
+                        free(sa);
+                        return -1;
+                }
+                len += sa[i]->srv_arg.len;
+                l = g_list_next(l);
+        }
+
+        r = (struct l7vs_service_arg_multi *)malloc(len);
+        if (r == NULL) {
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_SYSTEM_MEMORY,3, "list service_arg : Could not allocate memory" );
+                return -1;
+        }
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "memory allocated : address = %p , size = %d", r, len );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,21, debugstr );
+       }
+
+        s = r;
+        for (i = 0; i < n; i++) {
+                memcpy(s, sa[i], sa[i]->srv_arg.len);
+                s = (struct l7vs_service_arg_multi *)((uint8_t *)s + sa[i]->srv_arg.len);
+                l7vs_service_put_service_arg(sa[i]);
+        }
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "memory free : address = %p", sa );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,22, debugstr );
+       }
+        free(sa);
+        *sas = r;
+        *num = n;
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_list_service_arg(struct l7vs_service_arg_multi **sas, int *num)" );
+               sprintf( debugstr, "%s return : len = %d , sas = %p , num = %d", debugstr, len, sas, *num );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,23, debugstr );
+       }
+
+        return len;
+}
+
+/*!
+ * get l7vs_dest_arg lists
+ * @param[in] *srv     service pointer
+ * @param[out] **das   l7vs_dest_arg pointer list
+ * @return             pointer list count
+ */
+int
+l7vs_service_list_dest_arg(struct l7vs_service *srv,
+                           struct l7vs_dest_arg **das)
+{
+        GList *l;
+        struct l7vs_dest *d;
+        struct l7vs_dest_arg *darg;
+        int i, num;
+
+       if( NULL == srv ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,13, "list dest_arg : argument \"srv\" is NULL" );
+                return -1;
+       }
+       if( NULL == das ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,14, "list dest_arg : argument \"das\" is NULL" );
+                return -1;
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_list_dest_arg(struct l7vs_service *srv, struct l7vs_dest_arg **das)" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,24, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "srv dump" );
+               l7vs_service_c_str( debugstr, srv );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,25, debugstr );
+       }
+
+        num = g_list_length(srv->dest_list);
+        if (num == 0) {
+                *das = NULL;
+                return num;
+        }
+
+        darg = (struct l7vs_dest_arg *)malloc(num * sizeof(*darg));
+        if (darg == NULL) {
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_SYSTEM_MEMORY,4, "Could not allocate memory" );
+                return -1;
+        }
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "memory allocated : address = %p , size = %zu", darg, ( num * sizeof(*darg) ) );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,26, debugstr );
+       }
+
+        i = 0;
+        for (l = g_list_first(srv->dest_list); l != NULL; l = g_list_next(l)) {
+                d = (struct l7vs_dest *)l->data;
+                l7vs_dest_to_arg(d, &darg[i]);
+                i++;
+        }
+
+        *das = darg;
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_list_dest_arg(struct l7vs_service *srv, struct l7vs_dest_arg **das)" );
+               sprintf( debugstr, "%s return : num = %d , **darg = %p", debugstr, num, das );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,27, debugstr );
+       }
+
+        return num;
+}
+
+/*!
+ * create service instance. and set service value.
+ * @param[in]  *arg    l7vs_service_arg pointer
+ * @param[out] *err    error code
+ * @return             l7vs_service pointer
+ */
+struct l7vs_service *
+l7vs_service_create(struct l7vs_service_arg_multi *arg, int *err)
+{
+        struct l7vs_protomod *pmod;
+        struct l7vs_scheduler *sched;
+        struct l7vs_service *srv, *sref;
+        struct l7vs_lsock *lsock;
+       struct l7vs_dest *sorry_dest;   //! sorry-server destination
+//     struct l7vs_service_repdata *   service_replicationdata;
+
+       int ret = 0;
+        GList *l;
+
+       if( NULL == arg ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,15, "Could not create service : argument \"arg\" is NULL" );
+               return NULL;
+       }
+       if( NULL == err ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,16, "Could not create service : argument \"err\" is NULL" );
+               return NULL;
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_create(struct l7vs_service_arg_multi *arg, int *err)" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,28, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               l7vs_service_arg_multi_c_str( debugstr, arg );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,29, debugstr );
+       }
+
+        *err = 0;
+
+       /* max service guard */
+       if( g_list_length( l7vs_service_list ) >= MAX_SERVICES ){
+               LOGGER_PUT_LOG_INFO( LOG_CAT_L7VSD_VIRTUAL_SERVICE,4, "l7vsd max service is %d, new virtual service can't create.", MAX_SERVICES );
+               *err = L7VS_CONFIG_ERR_MAXVS_EXISTS;
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE )) {
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,30, "function l7vs_service_create( struct l7vs_service_arg_multi* arg, int *err ) return  : NULL (failure virtual service max limit" );
+               }
+               return NULL;
+       }
+
+        lsock = l7vs_lsock_get(&arg->srv_arg.addr, arg->srv_arg.proto, arg->srv_arg.backlog);
+        if (lsock == NULL) {
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_VIRTUAL_SERVICE,1, "Could not create listen socket" );
+                *err = L7VS_CONFIG_ERR_NOSOCK;
+               //debug output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "function l7vs_service_create(struct l7vs_service_arg_multi *arg, int *err) return : NULL (failure l7vs_lsock_get)" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,31, debugstr );
+               }
+                return NULL;
+        }
+
+        pmod = l7vs_protomod_get(arg->srv_arg.protomod);
+        if (pmod == NULL) {
+                l7vs_lsock_put(lsock);
+                *err = L7VS_CONFIG_ERR_NOMEM;
+               //debug output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "function l7vs_service_create(struct l7vs_service_arg_multi *arg, int *err) return : NULL (failure l7vs_protomod_get)" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,32, debugstr );
+               }
+                return NULL;
+        }
+
+        sched = l7vs_sched_get(arg->srv_arg.schedmod);
+        if (sched == NULL) {
+                l7vs_protomod_put(pmod);
+                l7vs_lsock_put(lsock);
+                *err = L7VS_CONFIG_ERR_NOSCHED;
+               //debug output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "function l7vs_service_create(struct l7vs_service_arg_multi *arg, int *err) return : NULL (failure l7vs_sched_get)" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,33, debugstr );
+               }
+                return NULL;
+        }
+
+       // create new destination for sorry-server (weight not set)
+    // FIXME ignore IPv6 address???
+       sorry_dest = (struct l7vs_dest *)l7vs_dest_create((struct sockaddr_in *)&arg->srv_arg.sorry_addr, 0);
+       if (sorry_dest == NULL) {
+               l7vs_sched_put(sched);
+               l7vs_protomod_put(pmod);
+               l7vs_lsock_put(lsock);
+                *err = L7VS_CONFIG_ERR_NOMEM;
+               //debug output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "function l7vs_service_create(struct l7vs_service_arg_multi *arg, int *err) return : NULL (failure l7vs_dest_create)" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,34, debugstr );
+               }
+               return NULL;
+       }
+
+       srv = (struct l7vs_service *) calloc(1, sizeof(struct l7vs_service));
+        if (srv == NULL) {
+               l7vs_dest_destroy(sorry_dest);
+                l7vs_sched_put(sched);
+                l7vs_protomod_put(pmod);
+                l7vs_lsock_put(lsock);
+                *err = L7VS_CONFIG_ERR_NOMEM;
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_SYSTEM_MEMORY,5, "l7vs_service memory allocate error" );
+                return NULL;
+        }
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "memory allocated : address = %p , size = %zu", srv, sizeof(struct l7vs_service ) );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,35, debugstr );
+       }
+
+       srv->handle = ++service_handle_base;
+       if( TEMP_SERVICEHANDLE == srv->handle ){
+               srv->handle = ++service_handle_base;
+       }
+        ret = pmod->create(&arg->protomod_arg, srv->handle);
+        if (ret != 0) {
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "memory free : address = %p", srv );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,36, debugstr );
+               }
+               free(srv);
+               l7vs_dest_destroy(sorry_dest);
+                l7vs_sched_put(sched);
+                l7vs_protomod_put(pmod);
+                l7vs_lsock_put(lsock);
+                *err = L7VS_CONFIG_ERR_NOMEM;
+               //debug output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "function l7vs_service_create(struct l7vs_service_arg_multi *arg, int *err) return : NULL (failure pmod create)" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,37, debugstr );
+               }
+                return NULL;
+        }
+
+        for (l = g_list_first(l7vs_service_list); l != NULL;
+             l = g_list_next(l)) {
+                sref = (struct l7vs_service *)l->data;
+
+                if (lsock != sref->lsock) {
+                        continue;
+                }
+
+                if (pmod != sref->pm) {
+                        continue;
+                }
+
+                if (pmod->compare(srv->handle, sref->handle) != 0) {
+                        continue;
+                }
+
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_VIRTUAL_SERVICE,2, "Virtual service already exists" );
+               l7vs_dest_destroy(sorry_dest);
+                l7vs_sched_put(sched);
+                l7vs_protomod_put(pmod);
+                l7vs_lsock_put(lsock);
+                pmod->destroy(srv->handle);
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "memory free : address = %p", srv );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,38, debugstr );
+               }
+               free(srv);
+                *err = L7VS_CONFIG_ERR_VS_EXISTS;
+               //debug output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "function l7vs_service_create(struct l7vs_service_arg_multi *arg, int *err) return : NULL (Duplication service)" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,39, debugstr );
+               }
+                return NULL;
+        }
+
+        srv->lsock = lsock;
+        srv->pm = pmod;
+        l7vs_sched_bind(sched, srv);
+
+       // set sorry data
+       srv->sorry_cc   = arg->srv_arg.sorry_cc;
+       srv->sorry_dest = sorry_dest;
+       srv->sorry_flag = arg->srv_arg.sorry_flag;
+       // set QoS value
+       srv->qos_threshold_up   = arg->srv_arg.qos_threshold_up;
+       srv->qos_threshold_down = arg->srv_arg.qos_threshold_down;
+
+        l7vs_lsock_add_service(lsock, srv);
+        l7vs_service_list = g_list_append(l7vs_service_list, srv);
+
+       // create g_hash_table
+       srv->conn_hash = g_hash_table_new( NULL, NULL );
+
+       // set replicationmode
+       // get the replication area.
+       unsigned int r_size = 0;
+       l7vs_service_repdata * repdata = (l7vs_service_repdata*)l7vs_replication_pay_memory( REP_COMP_SV, &r_size );
+       // if repdata is NULL, Cansel to replication mode
+       if( NULL != repdata ){
+               // if virtuar service number is 1, change mode and copy to the data.
+               if( 1 == g_list_length( l7vs_service_list ) ){
+                       l7vs_replication_switch_to_master();
+                       // when Syb->Act, Data is saved in a preliminary area of original Service.
+                       // The replication data area is calculated.  
+                       rep_size_num = (r_size * DATA_SIZE) / sizeof(struct l7vs_service_repdata);
+                       // get mirror area.
+                       rep_mirror = (struct l7vs_service_repdata*)calloc( rep_size_num, sizeof(struct l7vs_service_repdata) );
+                       // Copy to the data
+                       if( NULL != rep_mirror )memcpy( rep_mirror, repdata, (rep_size_num * sizeof(struct l7vs_service_repdata)) );
+                       //DEBUG output
+                       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                               char    debugstr[DEBUG_STR_LEN];
+                               memset( debugstr, 0, DEBUG_STR_LEN );
+                               sprintf( debugstr, "memory allocated : address = %p , size = %d", rep_mirror, (rep_size_num * sizeof(struct l7vs_service_repdata)) );
+                               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE, 95, debugstr );
+                       }
+               }
+               // if replication data mirror isn't NULL, get a rep_mirror area.
+               if( NULL != rep_mirror )set_replication_data( rep_size_num, rep_mirror, srv );
+               //make replication data
+               make_replication_data( rep_size_num, repdata );
+       }
+
+       //debug output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_create(struct l7vs_service_arg_multi *arg, int *err)" );
+               l7vs_service_c_str( debugstr, srv );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,40, debugstr );
+       }
+
+        return srv;
+}
+
+
+/*!
+ * append to conn remove list
+ * @param[in]  key     not use
+ * @param[in]  value   connection pointer
+ * @param[in]  userdata not use
+ */
+static void            rmvlistappend( gpointer key, gpointer value, gpointer userdata ){
+       removeconn_list = g_list_append( removeconn_list, value );
+}
+
+
+/*!
+ * service destroy function
+ * @param[in] *srv     service pointer
+ * @return    void
+ */
+int
+l7vs_service_destroy(struct l7vs_service *srv)
+{
+        struct l7vs_scheduler *sched;
+       struct l7vs_dest * rmv_dest;
+       struct l7vs_conn * rmvconn;
+//     struct l7vs_service_repdata *   service_replicationdata;
+
+
+       if( NULL == srv ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,17, "Service Destroy failure: argument is NULL" );
+               return -1;
+       }
+       
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_destroy(struct l7vs_service *srv)" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,41, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "srv dump" );
+               l7vs_service_c_str( debugstr, srv );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,42, debugstr );
+       }
+
+       //find service from glist(l7vs_service_list)
+       if( 0 == g_list_length( l7vs_service_list ) ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_VIRTUAL_SERVICE,3, "Service Destroy failure: service not created" );
+               return -1;
+       }
+       if( NULL == g_list_find( l7vs_service_list, srv ) ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_VIRTUAL_SERVICE,4, "Service Destroy failure: cannot find in list" );
+               return -1;
+       }
+       
+       // remove all hash-table members.
+       g_hash_table_foreach( srv->conn_hash, rmvlistappend, NULL );
+       
+       for( removeconn_list = g_list_first( removeconn_list );
+            removeconn_list != NULL; ){
+               rmvconn = (struct l7vs_conn*)removeconn_list->data;
+               l7vs_conn_destroy( rmvconn );
+               removeconn_list = g_list_remove( removeconn_list, rmvconn );
+       }
+       
+       // destroy g_hash_table
+       g_hash_table_destroy( srv->conn_hash );
+
+       // remove all dest(exclude sorry_dest)
+       for( srv->dest_list = g_list_first( srv->dest_list ); srv->dest_list != NULL; ){
+               rmv_dest = (struct l7vs_dest*)srv->dest_list->data;
+               srv->dest_list = g_list_remove( srv->dest_list, rmv_dest );
+               l7vs_dest_destroy( rmv_dest );
+       }
+
+       sched = srv->scheduler;
+       l7vs_service_list = g_list_remove(l7vs_service_list, srv);
+       l7vs_sched_unbind(sched, srv);
+       l7vs_dest_destroy(srv->sorry_dest);
+       l7vs_sched_put(sched);
+        l7vs_lsock_remove_service(srv->lsock, srv);
+        l7vs_lsock_put(srv->lsock);
+        srv->pm->destroy(srv->handle);
+       l7vs_protomod_put( srv->pm );
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "memory free : address = %p", srv );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,43, debugstr );
+       }
+       free(srv);
+
+       if( 0 == g_list_length( l7vs_service_list ) ){
+               l7vs_replication_switch_to_slave();
+       }
+
+       //make&set replication data
+//     service_replicationdata = (struct l7vs_service_repdata*)calloc(SERVICE_REPLICATION_MAX_NUM, sizeof(struct l7vs_service_repdata) );
+//     set_replication_data( SERVICE_REPLICATION_MAX_NUM, &service_replicationdata );
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_destroy(struct l7vs_service *srv) return : 0" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,44, debugstr );
+       }
+
+       return 0;
+}
+
+/*!
+ * serch from service list.
+ * @param[in]  *arg service arg
+ * @return     service pointer ( NULL is no lookup )
+ */
+struct l7vs_service *
+l7vs_service_lookup(struct l7vs_service_arg_multi *arg) //checks if the virtual service to be added already exists--Anshu
+{
+        GList *l;
+        struct l7vs_lsock *lsock;
+        struct l7vs_protomod *pmod;
+        struct l7vs_service *s, *sref;
+       int ret = 0;
+
+       if( NULL == arg ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,18, "Service lookup failure: agreement is NULL" );
+               return NULL;
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_lookup(struct l7vs_service_arg_multi *arg)" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,45, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "arg dump" );
+               l7vs_service_arg_multi_c_str( debugstr, arg );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,46, debugstr );
+       }
+
+        lsock = l7vs_lsock_table_lookup(&arg->srv_arg.addr, arg->srv_arg.proto);
+        if (lsock == NULL) {
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "l7vs_service_lookup(struct l7vs_service_arg_multi *arg) return : NULL (lsock table not found)" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,47, debugstr );
+               }
+                return NULL;
+        }
+
+        pmod = l7vs_protomod_lookup(arg->srv_arg.protomod);
+        if (pmod == NULL) {
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "l7vs_service_lookup(struct l7vs_service_arg_multi *arg) return : NULL (protomod not found)" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,48, debugstr );
+               }
+                return NULL;
+        }
+
+       s = (struct l7vs_service *) calloc(1, sizeof(struct l7vs_service));
+       if (s == NULL) {
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_SYSTEM_MEMORY,6, "l7vs_service memory allocate error" );
+               return NULL;
+       }
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "memory allocated : address = %p , size = %zu", s, sizeof(struct l7vs_service) );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,49, debugstr );
+       }
+
+       s->handle = TEMP_SERVICEHANDLE;
+        ret = pmod->create(&arg->protomod_arg, s->handle);
+       if (ret != 0) {
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "memory free : address = %p", s );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,50, debugstr );
+               }
+               free(s);
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "l7vs_service_lookup(struct l7vs_service_arg_multi *arg) return : NULL" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,51, debugstr );
+               }
+               return NULL;
+       }
+
+        for (l = g_list_first(l7vs_service_list);
+             l != NULL; l = g_list_next(l)) {
+                sref = (struct l7vs_service *)l->data;
+                if (lsock != sref->lsock) {
+                        continue;
+                }
+
+                if (pmod != sref->pm) {
+                        continue;
+                }
+
+                if (pmod->compare(s->handle, sref->handle) != 0) {
+                        continue;
+                }
+
+                pmod->destroy(s->handle);
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "memory free : address = %p", s );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,52, debugstr );
+               }
+               free(s);
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "function l7vs_service_lookup(struct l7vs_service_arg_multi *arg)" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,53, debugstr );
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "return l7vs_service dump" );
+                       l7vs_service_c_str( debugstr, sref );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,54, debugstr );
+               }
+
+                return sref;
+        }
+        if (s != NULL) {
+                pmod->destroy(s->handle);
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "memory free : address = %p", s );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,55, debugstr );
+               }
+               free(s);
+        } 
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "l7vs_service_lookup(struct l7vs_service_arg_multi *arg) return : NULL" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,56, debugstr );
+       }
+        return NULL;
+}
+
+/*!
+ * real server add on service
+ * @param[in]  *srv    service pointer
+ * @param[in]  *darg   l7vs_dest_arg pointer
+ * @return             success = 0 fail = -1
+ */
+int
+l7vs_service_add_dest(struct l7vs_service *srv,
+                      struct l7vs_dest_arg *darg)
+{
+        struct l7vs_dest *d;
+
+       if( NULL == srv || NULL == darg ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,19, "Service / add dest : Invalid argument" );
+               return -1;
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               char    deststr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_add_dest(struct l7vs_service *srv, struct l7vs_dest_arg *darg)" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,57, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "srv dump" );
+               l7vs_service_c_str( debugstr, srv );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,58, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               memset( deststr, 0, DEBUG_STR_LEN );
+               l7vs_dest_c_str( deststr, (l7vs_dest*)darg );
+               sprintf( debugstr, "dest dump %s", deststr );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,59, debugstr );
+       }
+
+        d = l7vs_service_lookup_dest(srv, &darg->addr);
+        if (d != NULL) {
+               LOGGER_PUT_LOG_INFO( LOG_CAT_L7VSD_VIRTUAL_SERVICE,5, "Cannot add duplicate real service" );
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "function l7vs_service_add_dest(struct l7vs_service *srv, struct l7vs_dest_arg *darg) return : -1" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,60, debugstr );
+               }
+                return -1;
+        }
+
+        d = (struct l7vs_dest*) l7vs_dest_create(&darg->addr, darg->weight);
+        if (d == NULL) {
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_REAL_SERVER,1, "Could not allocate memory" );
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "function l7vs_service_add_dest(struct l7vs_service *srv, struct l7vs_dest_arg *darg) return : -1" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,61, debugstr );
+               }
+                return -1;
+       }
+               else {
+                       LOGGER_PUT_LOG_INFO( LOG_CAT_L7VSD_VIRTUAL_SERVICE,6, "ADD_RS: IFRM004: added real server" );
+               }
+        
+        srv->dest_list = g_list_append(srv->dest_list, d);
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_add_dest(struct l7vs_service *srv, struct l7vs_dest_arg *darg) return : 0" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,62, debugstr );
+       }
+
+        return 0;
+}
+
+/* remove real server pointer function
+ * @param[in]  *srv    l7vs_service_pointer
+ * @param[in]   *darg  l7vs_dest pointer
+ * @return             success = 0 false = -1
+ */
+int
+l7vs_service_remove_dest(struct l7vs_service *srv,
+                         struct l7vs_dest_arg *darg)
+{
+       struct l7vs_dest *d;
+       struct l7vs_conn * tmp_conn;
+
+
+       if( NULL == srv || NULL == darg ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,20, "Service / remove dest : Invalid argument");
+               return -1;
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               char    deststr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_remove_dest(struct l7vs_service *srv, struct l7vs_dest_arg *darg)" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,63, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "srv dump" );
+               l7vs_service_c_str( debugstr, srv );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,64, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               memset( deststr, 0, DEBUG_STR_LEN );
+               l7vs_dest_c_str( deststr, (l7vs_dest*)darg );
+               sprintf( debugstr, "dest dump %s", deststr );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,65, debugstr );
+       }
+
+       d = l7vs_service_lookup_dest(srv, &darg->addr);
+        if (d == NULL) {
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_REAL_SERVER,2, "No such real server" );
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "function l7vs_service_remove_dest(struct l7vs_service *srv, struct l7vs_dest_arg *darg) return : -1" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,66, debugstr );
+               }
+                return -1;
+        }
+       else {
+               LOGGER_PUT_LOG_INFO( LOG_CAT_L7VSD_VIRTUAL_SERVICE,7, "DEL_RS: IFRM005: removed real server" );
+       }
+
+       g_hash_table_foreach( srv->conn_hash, rmvlistappend, NULL );
+       for( removeconn_list = g_list_first( removeconn_list ); removeconn_list != NULL; ){
+               tmp_conn = (struct l7vs_conn*)removeconn_list->data;
+               if( d == tmp_conn->dest ){
+                       l7vs_conn_destroy( tmp_conn );
+               }
+               removeconn_list = g_list_remove( removeconn_list, tmp_conn );
+       } 
+
+       srv->dest_list = g_list_remove(srv->dest_list, d);
+       l7vs_dest_destroy(d);
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_remove_dest(struct l7vs_service *srv, struct l7vs_dest_arg *darg) return : 0" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,67, debugstr );
+       }
+
+        return 0;
+}
+
+/*!
+ * schedule dest on con.(not use)
+ * @param[in] *srv     service pointer
+ * @param[in] *conn    l7vs_conn pointer
+ * @return             success = 0 false = -1
+ */
+int
+l7vs_service_schedule(struct l7vs_service *srv, 
+                      struct l7vs_conn *conn)
+{
+        struct l7vs_dest *dest;
+
+       if( NULL == srv || NULL == conn || NULL == srv->scheduler ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,21, "Service / lookup schedule-module : Invalid argument" );
+               return -1;
+       }
+
+        dest = srv->scheduler->schedule(srv, conn);
+        if (dest == NULL) {
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_SCHEDULE,1, "no real server defined" );
+                return -1;
+        }
+
+        return l7vs_conn_connect_rs(conn, dest);
+}
+
+
+/*!
+ * NOP
+ */
+int
+l7vs_service_establish(struct l7vs_service *srv, 
+                       struct l7vs_conn *conn)
+{
+        return 0;
+}
+
+/*!
+ * connection list append conn in service
+ * @param[in]  *srv    service pointer
+ * @param[in]  *conn   l7vs_conn pointer
+ * @return     void
+ */
+int
+l7vs_service_register_conn(struct l7vs_service *srv,
+                           struct l7vs_conn *conn)
+{
+       if( NULL == srv || NULL == conn ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,22, "register connection : Invalid argument" );
+               return -1;
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               char    connstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_register_conn(struct l7vs_service *srv, struct l7vs_conn *conn)" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,68, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "srv dump" );
+               l7vs_service_c_str( debugstr, srv );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,69, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               memset( connstr, 0, DEBUG_STR_LEN );
+               l7vs_conn_c_str( connstr, conn );
+               sprintf( debugstr, "conn dump %s", connstr );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,70, debugstr );
+       }
+
+       if( NULL != g_hash_table_lookup( srv->conn_hash, &conn->ciom->fd ) ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_VIRTUAL_SERVICE,5, "register connection : conflict connection." );
+               //DEBUG output
+               if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                       char    debugstr[DEBUG_STR_LEN];
+                       memset( debugstr, 0, DEBUG_STR_LEN );
+                       sprintf( debugstr, "function l7vs_service_register_conn(struct l7vs_service *srv, struct l7vs_conn *conn) return : -1" );
+                       LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,71, debugstr );
+               }
+               return -1;
+       }
+
+       g_hash_table_insert( srv->conn_hash, &conn->ciom->fd, conn );
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_register_conn(struct l7vs_service *srv, struct l7vs_conn *conn) return : 0" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,72, debugstr );
+       }
+       return 0;
+}
+
+/*!
+ * connection list delete con in service
+ * @param[in]  *srv    service pointer
+ * @param[in]  *conn   l7vs_conn pointer
+ * @return             void
+ */
+int
+l7vs_service_remove_conn(struct l7vs_service *srv, struct l7vs_conn *conn)
+{
+       if( NULL == srv || NULL == conn ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,23, "remove connection : Invalid argument" );
+               return -1;
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               char    connstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_remove_conn(struct l7vs_service *srv, struct l7vs_conn *conn)" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,73, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "srv dump" );
+               l7vs_service_c_str( debugstr, srv );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,74, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               memset( connstr, 0, DEBUG_STR_LEN );
+               l7vs_conn_c_str( connstr, conn );
+               sprintf( debugstr, "conn dump %s", connstr );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,75, debugstr );
+       }
+
+       g_hash_table_remove( srv->conn_hash, &conn->ciom->fd );
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_remove_conn(struct l7vs_service *srv, struct l7vs_conn *conn) return : 0" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,76, debugstr );
+       }
+       return 0;
+}
+
+/*!
+ * destroy all member in all service.
+ *
+ */
+void
+l7vs_service_flush_all(void)
+{
+       GList *l;
+       struct l7vs_service *srv;
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_flush_all()" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,77, debugstr );
+       }
+
+       while ((l = g_list_first(l7vs_service_list)) != NULL) {
+               srv = (struct l7vs_service *)l->data;
+               l7vs_service_destroy( srv );
+       }
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_flush_all() return" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,78, debugstr );
+       }
+}
+
+/*!
+ * set QoS(TraficControl) Threshold value
+ * @param[in]  *srv    service pointer
+ * @param[in]  *arg    l7vs_service_arg_multi pointer
+ * return              0 = success / -1 = failur
+ */
+int
+l7vs_service_set_QoS_Threshold( struct l7vs_service * srv, struct l7vs_service_arg_multi * arg )
+{
+//     struct l7vs_service_repdata *   service_replicationdata;
+
+       if( NULL == srv ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,24, "Argument srv is NULL" );
+               return -1;
+       }
+       if( NULL == arg ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,25, "Argument arg is NULL" );
+               return -1;
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_set_QoS_Threshold( struct l7vs_service * srv, struct l7vs_service_arg_multi * arg )" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,79, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "srv dump" );
+               l7vs_service_c_str( debugstr, srv );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,80, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "arg dump" );
+               l7vs_service_arg_multi_c_str( debugstr, arg );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,81, debugstr );
+       }
+
+       srv->qos_threshold_up   = arg->srv_arg.qos_threshold_up;
+       srv->qos_threshold_down = arg->srv_arg.qos_threshold_down;
+
+       // Get the replication area.
+       unsigned int r_size = 0;
+       l7vs_service_repdata * repdata = (l7vs_service_repdata*)l7vs_replication_pay_memory( REP_COMP_SV, &r_size );
+       // make replication data
+       if( NULL != repdata )make_replication_data( rep_size_num, repdata );
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_set_QoS_Threshold( struct l7vs_service * srv, struct l7vs_service_arg_multi * arg ) return : 0" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,82, debugstr );
+       }
+
+       return 0;
+}
+
+/*!
+ * set Sorry-Server values
+ * @param[in]   *srv    service pointer
+ * @param[in]   *arg    l7vs_service_arg_multi pointer
+ * return               0 = success / -1 = failure
+ */
+int
+l7vs_service_set_SorryServer_Values( struct l7vs_service * srv, struct l7vs_service_arg_multi * arg )
+{
+       struct sockaddr_in * saddr;
+//     struct l7vs_service_repdata *   service_replicationdata;
+
+       if( NULL == srv ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,26, "Argument srv is NULL" );
+               return -1;
+       }
+       if( NULL == arg ){
+               LOGGER_PUT_LOG_ERROR( LOG_CAT_L7VSD_PROGRAM,27, "Argument arg is NULL" );
+               return -1;
+       }
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_set_SorryServer_Values( struct l7vs_service * srv, struct l7vs_service_arg_multi * arg )" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,83, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "srv dump" );
+               l7vs_service_c_str( debugstr, srv );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,84, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "arg dump" );
+               l7vs_service_arg_multi_c_str( debugstr, arg );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,85, debugstr );
+       }
+       // set sorry data
+       saddr = (struct sockaddr_in *)&arg->srv_arg.sorry_addr;
+       srv->sorry_dest->addr   = *saddr;
+       srv->sorry_cc   = arg->srv_arg.sorry_cc;
+       srv->sorry_flag = arg->srv_arg.sorry_flag;
+
+       unsigned int r_size = 0;
+       l7vs_service_repdata *repdata = (l7vs_service_repdata*)l7vs_replication_pay_memory(REP_COMP_SV, &r_size);
+
+       //make replication data
+       if( NULL != repdata)
+       {
+               make_replication_data(rep_size_num, repdata);
+       }
+
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_set_SorryServer_Values( struct l7vs_service * srv, struct l7vs_service_arg_multi * arg ) return : 0" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,86, debugstr );
+       }
+
+       return 0;
+}
+
+/*!
+ * get number of l7vs_service list
+ * @param[in]  none
+ * @return     unsigned int
+ */
+unsigned int
+l7vs_service_get_VSnum()
+{
+       int     retval  = g_list_length( l7vs_service_list );
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_get_VSnum()" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,87, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_get_VSnum() return : num = retval" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,88, debugstr );
+       }
+       return  retval;
+}
+
+/*!
+ * find and get l7vs_service by number of l7vs_service_list
+ * @param[in]  num     number of l7vs_service list
+ * return      l7vs_service pointer
+ */
+struct l7vs_service *
+l7vs_service_get_VSInfo_byNum( unsigned int num )
+{
+       unsigned int vs_num = g_list_length( l7vs_service_list );
+       if( 0 > num )return NULL;
+       if( 0 == vs_num )return NULL;
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_get_VSInfo_byNum( unsigned int num )" );
+               sprintf( debugstr, "%s num = %d", debugstr, num );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,89, debugstr );
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_get_VSInfo_byNum( unsigned int num ) return" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,90, debugstr );
+       }
+       return (struct l7vs_service *)g_list_nth_data( l7vs_service_list, num );
+}
+
+/*!
+ * find and get l7vs_service by service-handle
+ * @param[in]  in_handle       l7vs_service handle
+ * return      l7vs_service pointer
+ */
+struct l7vs_service *
+l7vs_service_get_VSInfo_byHandler( handle_t in_handle )
+{
+       GList * l;
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_get_VSInfo_byHandler( handle_t in_handle )" );
+               sprintf( debugstr, "%s, in_handle = %d", debugstr, in_handle );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,91, debugstr );
+       }
+       for ( l = g_list_first(l7vs_service_list); l != NULL; l = g_list_next(l) ){
+               if( ((struct l7vs_service *)l->data)->handle == in_handle ){
+                       //DEBUG output
+                       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+                               char    debugstr[DEBUG_STR_LEN];
+                               memset( debugstr, 0, DEBUG_STR_LEN );
+                               sprintf( debugstr, "function l7vs_service_get_VSInfo_byHandler( handle_t in_handle ) return" );
+                               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,92, debugstr );
+                       }
+                       return (struct l7vs_service *)l->data;
+               }
+       }
+       //DEBUG output
+       if( LOG_LV_DEBUG == logger_get_log_level( LOG_CAT_L7VSD_VIRTUAL_SERVICE ) ){
+               char    debugstr[DEBUG_STR_LEN];
+               memset( debugstr, 0, DEBUG_STR_LEN );
+               sprintf( debugstr, "function l7vs_service_get_VSInfo_byHandler( handle_t in_handle ) return : NULL" );
+               LOGGER_PUT_LOG_DEBUG( LOG_CAT_L7VSD_VIRTUAL_SERVICE,93, debugstr );
+                       }
+       return  NULL;
+}
+
+void
+l7vs_service_update_throughput( struct l7vs_service* srv, unsigned long long current_time ) {
+       if ( LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_L7VSD_NETWORK_BANDWIDTH) ) {
+               char    srv_str[DEBUG_STR_LEN];
+               memset( srv_str, 0, DEBUG_STR_LEN );
+        l7vs_service_c_str(srv_str, srv);
+               LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_NETWORK_BANDWIDTH,1,"in_function: void l7vs_service_update_throughput(struct l7vs_service* srv, unsigned long long current_time) srv=%s, current_time=%llu", srv_str, current_time);
+       }
+    if (srv->pre_recvtime_from_client == current_time - 2) {
+        srv->pre_recvtime_from_client = current_time - 1;
+        srv->pre_recvsize_from_client = srv->cur_recvsize_from_client;
+        srv->cur_recvsize_from_client = 0;
+    }
+    else if (srv->pre_recvtime_from_client != current_time - 1) {
+        srv->pre_recvtime_from_client = current_time - 1;
+        srv->pre_recvsize_from_client = 0;
+        srv->cur_recvsize_from_client = 0;
+    }
+    if (srv->pre_recvtime_from_server == current_time - 2) {
+        srv->pre_recvtime_from_server = current_time - 1;
+        srv->pre_recvsize_from_server = srv->cur_recvsize_from_server;
+        srv->cur_recvsize_from_server = 0;
+    }
+    else if (srv->pre_recvtime_from_server != current_time - 1) {
+        srv->pre_recvtime_from_server = current_time - 1;
+        srv->pre_recvsize_from_server = 0;
+        srv->cur_recvsize_from_server = 0;
+    }
+       if ( LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_L7VSD_NETWORK_BANDWIDTH) ) {
+               LOGGER_PUT_LOG_DEBUG(LOG_CAT_L7VSD_VIRTUAL_SERVICE,2,"out_function: void l7vs_service_update_throughput(struct l7vs_service* srv, unsigned long long current_time)");
+       }
+}