/***************************************************************************
                   RCDB Control Class (RCDBControl.cpp)
                -----------------------------------------

	begin      : 2013/02/26
	copyright  : (C) 2013 Solbox Inc.
	author     : Development 1 Team
					- 2013/02/26 - 1st dadamin
	email      : dev1@solbox.com
	version    : 3.2.0

	CopyRight(C) 2005 Solbox Inc. All Rights reserved.
	Redistribution and use in source and binary forms, with or with out
	modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "rc_mngd.h"
#include "RCDBControl.h"
#include "Configs.h"
#include "DbConnPool.h"
#include "Database.h"
#include "Logger.h"
#include "UtilFn.h"
#include "Protocol.h"
#include <algorithm>

#define  USER_INFO_INSERT_COLUMN \
								"sp_user_seq,"\
								"sp_user_id,"\
								"sp_user_password"\

#define  USER_INFO_UPDATE_COLUMN \
								"sp_user_password"\

#define  PRODUCT_INSERT_COLUMN \
								"sp_user_seq,"\
								"sp_svc_tran_id,"\
								"sp_svc_id,"\
								"sp_svc_begin_date,"\
								"sp_svc_end_date,"\
								"max_bandwidth,"\
								"max_str_size,"\
								"initial_vector,"\
								"private_key,"\
								"validate_sp_session_id_yn,"\
								"bandwidth_ctrl_yn,"\
								"referer_chk_yn,"\
								"replication_count,"\
								"cal_used_depth,"\
								"uri_ignore_case,"\
								"del_file_keep_time"

#define  PRODUCT_UPDATE_COLUMN \
								"sp_svc_begin_date,"\
								"sp_svc_end_date,"\
								"max_bandwidth,"\
								"max_str_size,"\
								"initial_vector,"\
								"private_key,"\
								"validate_sp_session_id_yn,"\
								"bandwidth_ctrl_yn,"\
								"referer_chk_yn,"\
								"replication_count,"\
								"cal_used_depth,"\
								"uri_ignore_case,"\
								"del_file_keep_time"

#define  PRODUCT_EXT_AUTH_MODE_STR		KEY_REQ_AUTH_MODE
#define  PRODUCT_EXT_AUTH_INSERT_COLUMN \
								"sp_svc_tran_id,"\
								"sp_user_seq,"\
								PRODUCT_EXT_AUTH_MODE_STR","\
								"auth_server,"\
								"auth_path,"\
								"auth_port,"\
								"auth_timeout,"\
								"bill_server,"\
								"bill_path,"\
								"bill_port,"\
								"bill_timeout,"\
								"referer_chk_url,"\
								"referer_chk_filetype"

#define  PRODUCT_EXT_AUTH_UPDATE_COLUMN \
								PRODUCT_EXT_AUTH_MODE_STR","\
								"auth_server,"\
								"auth_path,"\
								"auth_port,"\
								"auth_timeout,"\
								"bill_server,"\
								"bill_path,"\
								"bill_port,"\
								"bill_timeout,"\
								"referer_chk_url,"\
								"referer_chk_filetype"

#define  PRODUCT_BAND_MODE_STR		KEY_REQ_BAND_MODE
#define  PRODUCT_BAND_INSERT_COLUMN \
								"sp_svc_tran_id,"\
								"sp_user_seq,"\
								PRODUCT_BAND_MODE_STR","\
								"volume_bandwidth_limit,"\
								"volume_bandwidth_current,"\
								"volume_bandwidth_before,"\
								"volume_bandwidth_control_current,"\
								"volume_bandwidth_control_before,"\
								"volume_bandwidth_update_datetime,"\
								"session_bandwidth_limit"

#define  PRODUCT_BAND_UPDATE_COLUMN \
								PRODUCT_BAND_MODE_STR","\
								"volume_bandwidth_limit,"\
								"session_bandwidth_limit"

#define  PRODUCT_SYNC_INSERT_COLUMN \
								"sp_svc_tran_id,"\
								"master_yn,"\
								"linked_sp_svc_tran_id,"\
								"linked_rcts"

#define  SERVICE_VOLUME_INSERT_COLUMN \
								"sp_user_seq,"\
								"sp_svc_tran_id,"\
								"depth,"\
								"path_name"

//2014.07.23 신균 형상(9.3)경우 대소문자 관련 기능 구현시 사용되는 값(display_name)이므로 개통 시 해당 값을 insert 해야됨
#define  SERVICE_ROOT_INSERT_COLUMN \
								"sp_user_seq,"\
								"sp_svc_tran_id,"\
								"host_name,"\
								KEY_URI","\
								"display_name"

#define  SERVICE_ROOT_UPDATE_COLUMN \
								"host_name,"\
								"get_etag,"\
								"deleted_yn,"\
								"file_lastmodified"

#define ANONYMOUS_INSERT_COLUMN \
								"sp_user_seq,"\
								"sp_svc_tran_id,"\
								KEY_URI

static string timeToString(time_t stamp)
{
	struct tm *_tm;
	char buf[30] = { 0 };

	_tm = localtime(&stamp);
	sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", (1900 + _tm->tm_year),
		(_tm->tm_mon + 1), _tm->tm_mday, _tm->tm_hour,
		_tm->tm_min, _tm->tm_sec);

	return string(buf);
}

static string timeSQL(int t)
{
	string r;
	string strNow = timeToString(time(NULL));
	
	switch (t)
	{
	case 1:
		// NOW(),NOW()
		r = "'" + strNow  + "','" + strNow + "'";
		break;
	case 2:
		// update_datetime = NOW()
		r = "update_datetime = '" + strNow + "'";
		break;
	default:
		break;
	}
	return r;
}

CRCDBControl::CRCDBControl()
	: m_pDB(NULL), m_used(CConnDBpool::POOL_ERR)
	, m_success(false), m_tabletype(-1), m_usedisplay(false)
{

}

CRCDBControl::~CRCDBControl()
{

}
void CRCDBControl::ForceClose()
{
	m_used = CConnDBpool::POOL_CLOSE;
}

int CRCDBControl::Init()
{
	int r = 0;

	if (CMasterDBpool::getInstance() == NULL)
		return -1;

	// database 
	m_pDB = CMasterDBpool::getInstance()->GetConnFromPool();

	// 2014.06.07 dadamin
	// DB 형상 설정
	m_tabletype = CMasterDBpool::getInstance()->GetTargetTableType();
	m_usedisplay = (m_tabletype == 1);

	if(m_pDB == NULL)
	{
		// failure to acquire Database
		m_used = CConnDBpool::POOL_ERR;
		r = -1;
	}
	else
	{
		r = 0;
		m_used = CConnDBpool::POOL_USE;
	}	
	
	return r;
}

int CRCDBControl::Final()
{
	int r = 0;

	if(m_pDB)
	{
		CMasterDBpool::getInstance()->ReleaseConnToPool(m_pDB, m_used);
		m_pDB = NULL;
	}

	return r;
}

bool CRCDBControl::BeginTrans()
{
	if(m_pDB)
	{
		if( m_pDB->PgDoExec("BEGIN WORK", DataBase::CLEAR) < 0)
		{
			// error
			m_used = CConnDBpool::POOL_ERR;
			LOG(LERR, "BeginTrans fail.[%s]", m_pDB->GetErrorMessage().c_str());
		}
		else
		{
			m_used = CConnDBpool::POOL_USE;
			LOG(LDBG, "BeginTrans Success.[BEGIN WORK]");			
		}
	}

	return (m_used == CConnDBpool::POOL_USE ? true : false);
}

bool CRCDBControl::EndTrans()
{
	if(m_pDB)
	{
		string sql;
		if(m_success)
			sql = "COMMIT WORK";
		else 
			sql = "ROLLBACK WORK";

		if( m_pDB->PgDoExec(const_cast<char*>(sql.c_str()), DataBase::CLEAR) < 0)
		{
			// error
			m_used = CConnDBpool::POOL_ERR;
			LOG(LERR, "EndTrans fail.[%s]", m_pDB->GetErrorMessage().c_str());
		}
		else
		{
			m_used = CConnDBpool::POOL_USE;
			LOG(LDBG, "EndTrans Success.[%s]", sql.c_str());
		}
	}

	return (m_used == CConnDBpool::POOL_USE ? true : false);
}

bool CRCDBControl::DoSQL(string sql, int nParamCnt, const char * const *paramValues)
{
	_LOG(LDBG, "RCDB SQL:%s", sql.c_str());
	if(nParamCnt == 0)
		m_pDB->PgDoExec(sql);
	else 
		m_pDB->PgDoExecParams(const_cast<char*>(sql.c_str()), nParamCnt, paramValues);
	// Query 결과를 가져온다.
	int nResult = m_pDB->PgResult(DataBase::NOT_CLEAR);
	if(nResult < 0)
	{
		m_used = CConnDBpool::POOL_ERR;
		LOG(LERR, "Database Error.[%s|%s]", sql.c_str(), m_pDB->GetErrorMessage().c_str());		
		return false;
	}
	
	return true;
}

bool CRCDBControl::DoSetSQL(string  sql,  int nParamCnt, const char * const *paramValues)
{
	_LOG(LDBG, "RCDB SQL2:%s", sql.c_str());
	if(nParamCnt == 0)
		m_pDB->PgDoExec(sql);
	else 
		m_pDB->PgDoExecParams(const_cast<char*>(sql.c_str()), nParamCnt, paramValues);

	// Query 결과를 가져온다.
	int nResult = m_pDB->PgResult(DataBase::CLEAR);
	if(nResult < 0)
	{
		m_used = CConnDBpool::POOL_ERR;
		LOG(LERR, "Database Error.[%s|%s]", sql.c_str(), m_pDB->GetErrorMessage().c_str());		
		return false;
	}

	return true;
}

bool CRCDBControl::CheckJobDataUserInfo(CJobDataMap & jobData, bool & hasuserseq, bool & hasuserid)
{
	if( jobData[KEY_SP_USER_SEQ].empty() )
	{
		hasuserseq = false;
		LOG(LDEV2, "User Information Jobdata empty.(%s)", KEY_SP_USER_SEQ);
	}

	if( jobData[KEY_SP_USER_ID].empty() )
	{
		hasuserid = false;
		LOG(LDEV2, "User Information Jobdata empty.(%s)", KEY_SP_USER_ID);
	}

	if( hasuserseq == false && hasuserid == false )
	{
		return false;
	}

	return true;
}

bool CRCDBControl::CheckJobDataSvcProduct(CJobDataMap & jobData, bool & hastranid, bool & hassvcid)
{
	if( jobData[KEY_SP_SVC_TRAN_ID].empty() )
	{
		hastranid = false;
		LOG(LDEV2, "Service Product Jobdata empty.(%s)", KEY_SP_SVC_TRAN_ID);
	}

	if( jobData[KEY_SP_SVC_ID].empty() )
	{
		hassvcid = false;
		LOG(LDEV2, "Service Product Jobdata empty.(%s)", KEY_SP_SVC_ID);
	}

	if( hastranid == false && hassvcid == false )
	{
		return false;
	}

	return true;
}

bool CRCDBControl::SetDB2JobData(bool & has, CJobDataMap & jobData, string valkey, const char * val)
{
	if(has)
	{
		if( jobData[valkey].compare(val) != 0 )
		{
			LOG(LWAR, "SetDB2JobData failed.[key:%s, J:%s, S:%s]"
				, valkey.c_str(), jobData[valkey].c_str(), val);
			return false;
		}
	}
	else
	{
		jobData[valkey] = val;
	}

	LOG(LDBG, "SetDB2JobData :has =%d, key = %s, val = %s", has, valkey.c_str(), val); 

	return true;
}

bool CRCDBControl::SetDB2JobData(CJobDataMap & jobData, string valkey, const char * val, bool force /* = false*/)
{
	bool r = true;
	bool exist = !(jobData[valkey].empty());

	if(force)
	{
		if(exist)
		{
			if( jobData[valkey].compare(val) != 0)
			{
				LOG(LWAR, "SetDB2JobData : Force mode, key = %s, val = %s=>%s",
					valkey.c_str(), jobData[valkey].c_str(), val); 
			}			
		}

		exist = false;
	}

	r = SetDB2JobData(exist, jobData, valkey, val);

	return r;
}

bool CRCDBControl::CheckUserInfo(CJobDataMap & jobData, bool & exist)
{
	// check t_sms_sp_user
	bool hasuserseq = true, hasuserid = true;

	if( CheckJobDataUserInfo(jobData, hasuserseq, hasuserid) == false )
	{
		LOG(LERR, "User Information Jobdata empty.(ALL)");
		return false;
	}

	int i = 0;
	const char *paramValues[2];
	ostringstream sql;

	sql << "SELECT sp_user_seq, sp_user_id, sp_user_password FROM t_sms_sp_user ";

	if (hasuserid && hasuserseq)
	{
		i = 2;
		sql << "WHERE " << "sp_user_id = $1 OR sp_user_seq = $2";
		paramValues[0] = jobData[KEY_SP_USER_ID].c_str();
		paramValues[1] = jobData[KEY_SP_USER_SEQ].c_str();
		
	}
	else if (hasuserid)
	{
		i = 1;
		sql << "WHERE " << "sp_user_id = $1";
		paramValues[0] = jobData[KEY_SP_USER_ID].c_str();
	}
	else 
	{
		i = 1;
		sql << "WHERE " << "sp_user_seq = $1";
		paramValues[0] = jobData[KEY_SP_USER_SEQ].c_str();
	}		

	if (DoSQL(sql.str(), i, paramValues))
	{
		bool r = true;
		if( m_pDB->GetNoTuples() == 1)
		{			
			r = SetDB2JobData(hasuserid, jobData, KEY_SP_USER_ID, m_pDB->GetValue(0, 1));
			if( r == false )
			{
				LOG(LNOT, "User Information difference(%s).[J:%s,D:%s]"
							, KEY_SP_USER_ID, jobData[KEY_SP_USER_ID].c_str()
							, m_pDB->GetValue(0, 1));
			}
			else
			{
				r = SetDB2JobData(hasuserseq, jobData, KEY_SP_USER_SEQ, m_pDB->GetValue(0, 0));
				if (r == false)
				{
					LOG(LNOT, "User Information difference(%s).[J:%s,D:%s]"
						, KEY_SP_USER_SEQ, jobData[KEY_SP_USER_SEQ].c_str()
						, m_pDB->GetValue(0, 0));
				}
			}

			if (r) exist = true;

		}
		else if ( m_pDB->GetNoTuples() > 1)
		{
			r = false;
			LOG(LNOT, "User Information duplicate.[J:%s,J:%s]",
				jobData[KEY_SP_USER_SEQ].c_str(), jobData[KEY_SP_USER_ID].c_str());
		}
		else
		{
			exist = false;
			LOG(LDBG, "User Information empty.[J:%s,J:%s]",
				jobData[KEY_SP_USER_SEQ].c_str(), jobData[KEY_SP_USER_ID].c_str());
		}

		if( r && exist )
		{
			if(jobData[KEY_SP_USER_PASSWORD].empty())
			{
				bool b = false;
				SetDB2JobData(b, jobData, KEY_SP_USER_PASSWORD, m_pDB->GetValue(0, 2));
			}
			LOG(LDBG, "User Information exist.[%s,%s]", 
				jobData[KEY_SP_USER_SEQ].c_str(), jobData[KEY_SP_USER_ID].c_str());
		}
		
		m_pDB->PgClear();
		return r;
	}

	return false;
}

bool CRCDBControl::CheckAnotherProduct(CJobDataMap & jobData, bool & exist)
{
	// check t_sms_sp_svc_product
	bool hastranid = true, hassvcid = true;
	if (CheckJobDataSvcProduct(jobData, hastranid, hassvcid) == false)
	{
		LOG(LERR, "Service Procuct Jobdata empty.(ALL)");
		return false;
	}

	const char *paramValues[2];
	ostringstream sql;

	sql << "SELECT sp_user_seq FROM t_sms_sp_svc_product WHERE sp_user_seq = ";

	if (!hassvcid)
	{
		sql << "(SELECT sp_user_seq FROM t_sms_sp_svc_product WHERE sp_svc_tran_id = $1)";
		sql << "AND sp_svc_tran_id != $2";
		paramValues[0] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
		paramValues[1] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
	}
	else
	{
		sql << "(SELECT sp_user_seq FROM t_sms_sp_svc_product WHERE sp_svc_id = $1)";
		sql << "AND sp_svc_id != $2";
		paramValues[0] = jobData[KEY_SP_SVC_ID].c_str();
		paramValues[1] = jobData[KEY_SP_SVC_ID].c_str();
	}
	
	
	if (DoSQL(sql.str(), 2, paramValues))
	{
		if (m_pDB->GetNoTuples() > 0)
		{
			exist = true;
			LOG(LINF, "Another Product exist.[user:%s]", paramValues[0]);
		}		
		else
		{
			exist = false;
			LOG(LINF, "Another Product empty.[user:%s]", paramValues[0]);
		}		

		m_pDB->PgClear();
		return true;
	}

	return false;
}

bool CRCDBControl::CheckProductInfo(CJobDataMap & jobData, bool & exist)
{
	// check t_sms_sp_svc_product
	bool hasuserseq = true, hasuserid = true;
	bool hastranid = true, hassvcid = true;

	CheckJobDataUserInfo(jobData, hasuserseq, hasuserid);

	if ( CheckJobDataSvcProduct(jobData, hastranid, hassvcid) == false )
	{
		LOG(LERR, "Service Procuct Jobdata empty.(ALL)");
		return false;
	}

	int i = 0;
	const char *paramValues[2];
	ostringstream sql;

	sql << "SELECT U.sp_user_seq, U.sp_user_id, P.sp_svc_tran_id, P.sp_svc_id " 
		<< "FROM t_sms_sp_svc_product AS P "
		<< "LEFT OUTER JOIN  t_sms_sp_user AS U ON P.sp_user_seq = U.sp_user_seq";
	
	if (hastranid && hassvcid)
	{
		i = 2;
		sql << " WHERE P.sp_svc_tran_id = $1 OR P.sp_svc_id = $2";
		paramValues[0] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
		paramValues[1] = jobData[KEY_SP_SVC_ID].c_str();
	}
	else if(hastranid)
	{
		i = 1;
		sql << " WHERE P.sp_svc_tran_id = $1";
		paramValues[0] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
	}
	else 
	{
		i = 1;
		sql << " WHERE P.sp_svc_id = $1";
		paramValues[0] = jobData[KEY_SP_SVC_ID].c_str();
	}
	
	if( DoSQL(sql.str(), i, paramValues) )
	{
		bool r = true;
		if( m_pDB->GetNoTuples() == 1)
		{
			if(strlen(m_pDB->GetValue(0, 0)) == 0)
			{
				r = false;
				LOG(LNOT, "Service Product exist. But User Information empty.[J:%s,J:%s]",
					jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else 
			{
				r = SetDB2JobData(hassvcid, jobData, KEY_SP_SVC_ID, m_pDB->GetValue(0, 3));
				if(r == false)
				{
					LOG(LNOT, "Service Product difference(%s).[J:%s,D:%s]", KEY_SP_SVC_ID
						, jobData[KEY_SP_SVC_ID].c_str(), m_pDB->GetValue(0, 3));
				}
				else
				{
					r = SetDB2JobData(hastranid, jobData, KEY_SP_SVC_TRAN_ID, m_pDB->GetValue(0, 2));
					if (r == false)
					{
						LOG(LNOT, "Service Product difference(%s).[J:%s,D:%s]", KEY_SP_SVC_TRAN_ID
							, jobData[KEY_SP_SVC_TRAN_ID].c_str(), m_pDB->GetValue(0, 2));
					}					
				}
				
				if (r) exist = true;
			}

			if( r && exist )
			{
				r = SetDB2JobData(hasuserseq, jobData, KEY_SP_USER_SEQ, m_pDB->GetValue(0, 0));
				if(r == false)
				{
					LOG(LNOT, "Service Product exist. But User Information difference(%s)[J:%s].[J:%s,J:%s]"
							, KEY_SP_USER_SEQ,jobData[KEY_SP_USER_SEQ].c_str(), 
							jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}
				
				r = SetDB2JobData(hasuserid, jobData, KEY_SP_USER_ID, m_pDB->GetValue(0, 1));
				if(r == false)
				{
					LOG(LNOT, "Service Product exist. But User Information difference(%s)[J:%s].[J:%s,J:%s]"
							, KEY_SP_USER_ID, jobData[KEY_SP_USER_ID].c_str(), 
							jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}
			}
		}
		else if ( m_pDB->GetNoTuples() > 1)
		{
			r = false;
			LOG(LNOT, "Service Product duplicate.[J:%s,J:%s]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}
		else
		{
			exist = false;
			LOG(LDBG, "Service Product empty.[J:%s,J:%s]", 
				jobData[KEY_SP_SVC_TRAN_ID].c_str(),jobData[KEY_SP_SVC_ID].c_str());
		}

		if( r && exist )
		{
			LOG(LDBG, "Service Product exist.[%s,%s]", 
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}
		
		m_pDB->PgClear();
		return r;
	}

	return false;
}

bool CRCDBControl::CheckProductExtAuth(CJobDataMap & jobData, bool & exist)
{
	// check t_sms_sp_svc_product_val
	bool hasuserseq = true, hasuserid = true;
	bool hastranid = true, hassvcid = true;

	CheckJobDataUserInfo(jobData, hasuserseq, hasuserid);

	if ( CheckJobDataSvcProduct(jobData, hastranid, hassvcid) == false )
	{
		LOG(LERR, "Service Procuct(Auth) Jobdata empty.(ALL)");
		return false;
	}

	const char *paramValues[1];

	ostringstream sql;

	sql << "SELECT U.sp_user_seq, U.sp_user_id, P.sp_user_seq, P.sp_svc_tran_id, P.sp_svc_id, PV.sp_user_seq, PV.sp_svc_tran_id "
		//<< "FROM t_sms_sp_svc_product_val AS PV LEFT OUTER JOIN t_sms_sp_svc_product AS P USING (sp_svc_tran_id,sp_user_seq)"
		<< "FROM t_sms_sp_svc_product_val AS PV "
		<< " LEFT OUTER JOIN t_sms_sp_svc_product AS P ON PV.sp_svc_tran_id = P.sp_svc_tran_id"
		<< ",t_sms_sp_svc_product_val AS PV2 "
		<< " LEFT OUTER JOIN t_sms_sp_user AS U ON PV2.sp_user_seq = U.sp_user_seq "
		<< "WHERE PV2.sp_svc_tran_id = PV.sp_svc_tran_id";

	if(hastranid)
	{
		sql << " AND PV.sp_svc_tran_id = $1";
		paramValues[0] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
	}
	else 
	{
		sql << " AND PV.sp_svc_tran_id ="
			<< "(SELECT sp_svc_tran_id FROM t_sms_sp_svc_product WHERE sp_svc_id = $1)";
		paramValues[0] = jobData[KEY_SP_SVC_ID].c_str();
	}
	
	if( DoSQL(sql.str(), 1, paramValues) )
	{
		bool r = true;

		if( m_pDB->GetNoTuples() == 1)
		{
			if(strlen(m_pDB->GetValue(0, 0)) == 0)
			{
				r = false;
				LOG(LNOT, "Service Product Extensions(auth) exist. But User Information empty.[J:%s,J:%s]",
					jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else if (strlen(m_pDB->GetValue(0, 2)) == 0)
			{
				r = false;
				LOG(LNOT, "Service Product Extensions(auth) exist. But Service Product empty.[J:%s,J:%s]",
					jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else if (strcmp(m_pDB->GetValue(0, 0),m_pDB->GetValue(0, 2)) != 0 )
			{
				r = false;
				LOG(LNOT, "User & Product difference(sp_user_seq).[U:%s,P:%s][J:%s,J:%s]"
					,m_pDB->GetValue(0, 0),m_pDB->GetValue(0, 2)
					,jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else if(hastranid)
			{
				r = SetDB2JobData(hassvcid, jobData, KEY_SP_SVC_ID, m_pDB->GetValue(0, 4));
				if(r == false)
				{
					LOG(LNOT, "Service Product difference(sp_svc_id).[J:%s,J:%s]"
						,jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}
				else
				{
					exist = true;
				}
			}
			else
			{
				exist = true;
				SetDB2JobData(hastranid, jobData, KEY_SP_SVC_TRAN_ID, m_pDB->GetValue(0, 3));
			}

			if( r && exist )
			{
				r = SetDB2JobData(hasuserseq, jobData, KEY_SP_USER_SEQ, m_pDB->GetValue(0, 0));
				if(r == false)
				{
					LOG(LNOT, "Service Product Extensions(auth) exist. But User Information difference(sp_user_seq)[J:%s].[J:%s,J:%s]",
						jobData[KEY_SP_USER_SEQ].c_str(), jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}

				r = SetDB2JobData(hasuserid, jobData, KEY_SP_USER_ID, m_pDB->GetValue(0, 1));
				if(r == false)
				{
					LOG(LNOT, "Service Product Extensions(auth) exist. But User Information difference(sp_user_id)[J:%s].[J:%s,J:%s]",
						jobData[KEY_SP_USER_ID].c_str(), jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}
			}
		}
		else if ( m_pDB->GetNoTuples() > 1)
		{
			r = false;
			LOG(LNOT, "Service Product Extensions(auth) duplicate.[J:%s,J:%s]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}
		else
		{
			exist = false;
			LOG(LDBG, "Service Product Extensions(auth) empty.[J:%s,J:%s]", 
				jobData[KEY_SP_SVC_TRAN_ID].c_str(),jobData[KEY_SP_SVC_ID].c_str());
		}

		if( r && exist )
		{
			LOG(LDBG, "Service Product Extensions(auth) exist.[%s,%s]", 
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}

		m_pDB->PgClear();
		return r;
	}

	return false;
}

bool CRCDBControl::CheckProductExtBand(CJobDataMap & jobData, bool & exist)
{
	// check t_sms_sp_svc_product_band

	bool hasuserseq = true, hasuserid = true;
	bool hastranid = true, hassvcid = true;

	CheckJobDataUserInfo(jobData, hasuserseq, hasuserid);

	if ( CheckJobDataSvcProduct(jobData, hastranid, hassvcid) == false )
	{
		LOG(LERR, "Service Procuct(bandwidth) Jobdata empty.(ALL)");
		return false;
	}

	const char *paramValues[1];

	ostringstream sql;

	sql << "SELECT U.sp_user_seq, U.sp_user_id, P.sp_user_seq, P.sp_svc_tran_id, P.sp_svc_id, PB.sp_user_seq, PB.sp_svc_tran_id "
		<< "FROM t_sms_sp_svc_product_band AS PB "
		<< " LEFT OUTER JOIN t_sms_sp_svc_product AS P ON PB.sp_svc_tran_id = P.sp_svc_tran_id"
		<< ",t_sms_sp_svc_product_band AS PB2 "
		<< " LEFT OUTER JOIN t_sms_sp_user AS U ON PB2.sp_user_seq = U.sp_user_seq "
		<< "WHERE PB2.sp_svc_tran_id = PB.sp_svc_tran_id";
	
	if(hastranid)
	{
		sql << " AND PB.sp_svc_tran_id = $1";
		paramValues[0] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
	}
	else 
	{
		sql << " AND PB.sp_svc_tran_id ="
			<< "(SELECT sp_svc_tran_id FROM t_sms_sp_svc_product WHERE sp_svc_id = $1)";
		paramValues[0] = jobData[KEY_SP_SVC_ID].c_str();
	}

	if( DoSQL(sql.str(), 1, paramValues) ) 
	{
		bool r = true;
		if( m_pDB->GetNoTuples() == 1)
		{
			if(strlen(m_pDB->GetValue(0, 0)) == 0)
			{
				r = false;
				LOG(LNOT, "Service Product Extensions(bandwidth) exist. But User Information empty.[J:%s,J:%s]",
					jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else if (strlen(m_pDB->GetValue(0, 2)) == 0)
			{
				r = false;
				LOG(LNOT, "Service Product Extensions(bandwidth) exist. But Service Product empty.[J:%s,J:%s]",
					jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else if (strcmp(m_pDB->GetValue(0, 0),m_pDB->GetValue(0, 2)) != 0 )
			{
				r = false;
				LOG(LNOT, "User & Product difference(sp_user_seq).[U:%s,P:%s][J:%s,J:%s]"
					,m_pDB->GetValue(0, 0),m_pDB->GetValue(0, 2)
					,jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else if(hastranid)
			{
				r = SetDB2JobData(hassvcid, jobData, KEY_SP_SVC_ID, m_pDB->GetValue(0, 4));
				if(r == false)
				{
					LOG(LNOT, "Service Product difference(bandwidth).[J:%s,J:%s]"
						,jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}
				else
				{
					exist = true;
				}
			}
			else
			{
				exist = true;
				SetDB2JobData(hastranid, jobData, KEY_SP_SVC_TRAN_ID, m_pDB->GetValue(0, 3));
			}

			if( r && exist )
			{
				r = SetDB2JobData(hasuserseq, jobData, KEY_SP_USER_SEQ, m_pDB->GetValue(0, 0));
				if(r == false)
				{
					LOG(LNOT, "Service Product Extensions(bandwidth) exist. But User Information difference(sp_user_seq)[J:%s].[J:%s,J:%s]",
						jobData[KEY_SP_USER_SEQ].c_str(), jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}

				r = SetDB2JobData(hasuserid, jobData, KEY_SP_USER_ID, m_pDB->GetValue(0, 1));
				if(r == false)
				{
					LOG(LNOT, "Service Product Extensions(bandwidth) exist. But User Information difference(sp_user_id)[J:%s].[J:%s,J:%s]",
						jobData[KEY_SP_USER_ID].c_str(), jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}
			}
		}
		else if ( m_pDB->GetNoTuples() > 1)
		{
			r = false;
			LOG(LNOT, "Service Product Extensions(bandwidth) duplicate.[J:%s,J:%s]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}
		else
		{
			exist = false;
			LOG(LDBG, "Service Product Extensions(bandwidth) empty.[J:%s,J:%s]", 
				jobData[KEY_SP_SVC_TRAN_ID].c_str(),jobData[KEY_SP_SVC_ID].c_str());
		}

		if( r && exist )
		{
			LOG(LDBG, "Service Product Extensions(bandwidth) exist.[%s,%s]", 
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}

		m_pDB->PgClear();
		return r;
	}

	return false;
}

bool CRCDBControl::CheckProductSync(CJobDataMap & jobData, bool & exist)
{
	// check t_sms_sp_svc_product_band

	bool hasuserseq = true, hasuserid = true;
	bool hastranid = true, hassvcid = true;

	CheckJobDataUserInfo(jobData, hasuserseq, hasuserid);

	if (CheckJobDataSvcProduct(jobData, hastranid, hassvcid) == false)
	{
		LOG(LERR, "Service Procuct(sync) Jobdata empty.(ALL)");
		return false;
	}

	if (jobData[KEY_LINK_SP_SVC_TRAN_ID].empty() && jobData[KEY_LINK_RCTS].empty())
	{
		exist = false;
		LOG(LWAR, "Service Procuct(sync) Jobdata link empty.");
		return true;
	}

	ostringstream sql;

	sql << "SELECT P.sp_user_seq, P.sp_svc_tran_id, P.sp_svc_id, PS.master_yn, PS.linked_sp_svc_tran_id, PS.linked_rcts "
		<< "FROM t_sms_sp_svc_product_sync AS PS "
		<< " LEFT OUTER JOIN t_sms_sp_svc_product AS P ON PS.sp_svc_tran_id = P.sp_svc_tran_id ";

	const char *paramValues[4];
	int index = 3;

	sql << "WHERE ";

	if (hastranid)
	{
		sql << "PS.sp_svc_tran_id = $1 ";
		paramValues[0] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
	}
	else
	{
		sql << "PS.sp_svc_tran_id = "
			<< "(SELECT sp_svc_tran_id FROM t_sms_sp_svc_product WHERE sp_svc_id = $1) ";
		paramValues[0] = jobData[KEY_SP_SVC_ID].c_str();
	}

	sql << "AND PS.linked_sp_svc_tran_id = $2 ";
	paramValues[1] = jobData[KEY_LINK_SP_SVC_TRAN_ID].c_str();

	sql << "AND PS.linked_rcts = $3 ";
	paramValues[2] = jobData[KEY_LINK_RCTS].c_str();
	
	if (jobData[KEY_LINK_MASTER_YN].size())
	{
		index = 4;
		sql << "AND PS.master_yn = $4 ";
		paramValues[3] = jobData[KEY_LINK_MASTER_YN].c_str();
	}

	if (DoSQL(sql.str(), index, paramValues))
	{
		bool r = true;
		if (m_pDB->GetNoTuples() == 1)
		{
			if (strlen(m_pDB->GetValue(0, 0)) == 0)
			{
				r = false;
				LOG(LNOT, "Service Product sync exist. But Service Product empty.[J:%s,J:%s]",
					jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else 
			{
				r = SetDB2JobData(hasuserseq, jobData, KEY_SP_USER_SEQ, m_pDB->GetValue(0, 0));
				if (r == false)
				{
					LOG(LNOT, "Service Product sync exist. But User Information difference(sp_user_seq)[J:%s].[J:%s,J:%s]",
						jobData[KEY_SP_USER_SEQ].c_str(), jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());

				}
				else
				{
					SetDB2JobData(hastranid, jobData, KEY_SP_SVC_TRAN_ID, m_pDB->GetValue(0, 1));
					SetDB2JobData(hassvcid, jobData, KEY_SP_SVC_ID, m_pDB->GetValue(0, 2));

					if (jobData[KEY_LINK_MASTER_YN].compare(m_pDB->GetValue(0, 3)) != 0)
					{
						LOG(LNOT, "Service Product sync exist. But Information difference(master_yn)[J:%s,J:%s]",
							jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
						r = false;
					}
					else 
						exist = true;
				}			
			}				
		}
		else if (m_pDB->GetNoTuples() > 1)
		{
			r = false;
			LOG(LNOT, "Service Product sync duplicate.[J:%s,J:%s]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}
		else
		{
			exist = false;
			LOG(LDBG, "Service Product sync empty.[J:%s,J:%s]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}

		m_pDB->PgClear();
		return r;
	}

	return false;
}

bool CRCDBControl::CheckVolumeInfo(CJobDataMap & jobData, bool & exist)
{
	// check t_dav_use_dir
	bool hasuserseq = true, hasuserid = true;
	bool hastranid = true, hassvcid = true;

	CheckJobDataUserInfo(jobData, hasuserseq, hasuserid);

	if (CheckJobDataSvcProduct(jobData, hastranid, hassvcid) == false)
	{
		LOG(LERR, "Service Procuct Jobdata empty.(ALL)");
		return false;
	}

	const char *paramValues[1];

	ostringstream sql;

	sql << "SELECT U.sp_user_seq, U.sp_user_id, P.sp_user_seq, P.sp_svc_tran_id, P.sp_svc_id, DU.sp_user_seq, DU.sp_svc_tran_id "
		//<< "FROM t_sms_sp_svc_product_val AS PV LEFT OUTER JOIN t_sms_sp_svc_product AS P USING (sp_svc_tran_id,sp_user_seq)"
		<< "FROM t_dav_use_dir AS DU "
		<< " LEFT OUTER JOIN t_sms_sp_svc_product AS P ON DU.sp_svc_tran_id = P.sp_svc_tran_id"
		<< ",t_dav_use_dir AS DU2 "
		<< " LEFT OUTER JOIN t_sms_sp_user AS U ON DU2.sp_user_seq = U.sp_user_seq "
		<< "WHERE DU2.sp_svc_tran_id = DU.sp_svc_tran_id";
	
	sql << " AND DU2.depth = DU.depth AND DU.depth = 0";

	if (hastranid)
	{
		sql << " AND DU.sp_svc_tran_id = $1";
		paramValues[0] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
	}
	else
	{
		sql << " AND DU.sp_svc_tran_id ="
			<< "(SELECT sp_svc_tran_id FROM t_sms_sp_svc_product WHERE sp_svc_id = $1)";
		paramValues[0] = jobData[KEY_SP_SVC_ID].c_str();
	}

	if (DoSQL(sql.str(), 1, paramValues))
	{
		bool r = true;
		if (m_pDB->GetNoTuples() == 1)
		{
			if (strlen(m_pDB->GetValue(0, 0)) == 0)
			{
				r = false;
				LOG(LNOT, "Service Product Extensions(volume) exist. But User Information empty.[J:%s,J:%s]",
					jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else if (strlen(m_pDB->GetValue(0, 2)) == 0)
			{
				r = false;
				LOG(LNOT, "Service Product Extensions(volume) exist. But Service Product empty.[J:%s,J:%s]",
					jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else if (strcmp(m_pDB->GetValue(0, 0), m_pDB->GetValue(0, 2)) != 0)
			{
				r = false;
				LOG(LNOT, "User & Product difference(sp_user_seq).[U:%s,P:%s][J:%s,J:%s]"
					, m_pDB->GetValue(0, 0), m_pDB->GetValue(0, 2)
					, jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else if (hastranid)
			{
				r = SetDB2JobData(hassvcid, jobData, KEY_SP_SVC_ID, m_pDB->GetValue(0, 4));
				if (r == false)
				{
					LOG(LNOT, "Service Product difference(volume).[J:%s,J:%s]"
						, jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}
				else
				{
					exist = true;
				}
			}
			else
			{
				exist = true;
				SetDB2JobData(hastranid, jobData, KEY_SP_SVC_TRAN_ID, m_pDB->GetValue(0, 3));
			}

			if (r && exist)
			{
				r = SetDB2JobData(hasuserseq, jobData, KEY_SP_USER_SEQ, m_pDB->GetValue(0, 0));
				if (r == false)
				{
					LOG(LNOT, "Service Product Extensions(volume) exist. But User Information difference(sp_user_seq)[J:%s].[J:%s,J:%s]",
						jobData[KEY_SP_USER_SEQ].c_str(), jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}

				r = SetDB2JobData(hasuserid, jobData, KEY_SP_USER_ID, m_pDB->GetValue(0, 1));
				if (r == false)
				{
					LOG(LNOT, "Service Product Extensions(volume) exist. But User Information difference(sp_user_id)[J:%s].[J:%s,J:%s]",
						jobData[KEY_SP_USER_ID].c_str(), jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}
			}
		}
		else if (m_pDB->GetNoTuples() > 1)
		{
			r = false;
			LOG(LNOT, "Service Product Extensions(volume) duplicate.[J:%s,J:%s]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}
		else
		{
			exist = false;
			LOG(LDBG, "Service Product Extensions(volume) empty.[J:%s,J:%s]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}

		if (r && exist)
		{
			LOG(LDBG, "Service Product Extensions(volume) exist.[%s,%s]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}

		m_pDB->PgClear();
		return r;
	}

	return false;
}

bool CRCDBControl::CheckRootInfo(CJobDataMap & jobData, bool & exist)
{
	// check meta table
	bool hasuserseq = true, hasuserid = true;
	bool hastranid = true, hassvcid = true;

	CheckJobDataUserInfo(jobData, hasuserseq, hasuserid);

	if ( CheckJobDataSvcProduct(jobData, hastranid, hassvcid) == false )
	{
		LOG(LERR, "Service Procuct(Root Info) Jobdata empty.(ALL)");
		return false;
	}

	// 2014.06.07 dadamin 
	// 형상(9.3) 변경으로 테이블명 변경
	string tblname;
	if (jobData[KEY_SP_SVC_TRAN_ID].size() <= 0)
	{
		LOG(LERR, "There is no information about the service requested(Root Info - tran_id).");
		return false;
	}

	tblname = GetMataTableName(jobData[KEY_SP_SVC_TRAN_ID].c_str());

	const char *paramValues[1];

	ostringstream sql;

	sql << "SELECT U.sp_user_seq, U.sp_user_id, P.sp_user_seq, P.sp_svc_tran_id, P.sp_svc_id, R.sp_user_seq, R.sp_svc_tran_id "
		<< "FROM " << tblname << " AS R "
		<< " LEFT OUTER JOIN t_sms_sp_svc_product AS P ON R.sp_svc_tran_id = P.sp_svc_tran_id"
		<< ", " << tblname << " AS R2 "
		<< " LEFT OUTER JOIN t_sms_sp_user AS U ON R2.sp_user_seq = U.sp_user_seq "
		<< "WHERE R2.sp_svc_tran_id = R.sp_svc_tran_id AND R2.depth = R.depth "
		<< "AND R2.deleted_yn = R.deleted_yn AND R2.is_cache = R.is_cache AND R2.resource_type = R.resource_type "
		<< "AND R.depth = 0 AND R.deleted_yn = 'N' AND R.is_cache = 'N' AND R2.resource_type = 1";

	if(hastranid)
	{
		sql << " AND R.sp_svc_tran_id = $1";
		paramValues[0] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
	}
	else 
	{
		sql << " AND R.sp_svc_tran_id ="
			<< "(SELECT sp_svc_tran_id FROM t_sms_sp_svc_product WHERE sp_svc_id = $1)";
		paramValues[0] = jobData[KEY_SP_SVC_ID].c_str();
	}

	if( DoSQL(sql.str(), 1, paramValues) )
	{
		bool r = true;
		if( m_pDB->GetNoTuples() == 1)
		{
			if(strlen(m_pDB->GetValue(0, 0)) == 0)
			{
				r = false;
				LOG(LNOT, "Service Product Root exist. But User Information empty.[J:%s,J:%s]",
					jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else if (strlen(m_pDB->GetValue(0, 2)) == 0)
			{
				r = false;
				LOG(LNOT, "Service Product Root exist. But Service Product empty.[J:%s,J:%s]",
					jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else if (strcmp(m_pDB->GetValue(0, 0),m_pDB->GetValue(0, 2)) != 0 )
			{
				r = false;
				LOG(LNOT, "User & Product difference(sp_user_seq).[U:%s,P:%s][J:%s,J:%s]"
					,m_pDB->GetValue(0, 0),m_pDB->GetValue(0, 2)
					,jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else if(hastranid)
			{
				r = SetDB2JobData(hassvcid, jobData, KEY_SP_SVC_ID, m_pDB->GetValue(0, 4));
				if(r == false)
				{
					LOG(LNOT, "Service Product difference(Root).[J:%s,J:%s]"
						,jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}
				else
				{
					exist = true;
				}
			}
			else
			{
				exist = true;
				SetDB2JobData(hastranid, jobData, KEY_SP_SVC_TRAN_ID, m_pDB->GetValue(0, 3));
			}

			if( r && exist )
			{
				r = SetDB2JobData(hasuserseq, jobData, KEY_SP_USER_SEQ, m_pDB->GetValue(0, 0));
				if(r == false)
				{
					LOG(LNOT, "Service Product Root exist. But User Information difference(sp_user_seq)[J:%s].[J:%s,J:%s]",
						jobData[KEY_SP_USER_SEQ].c_str(), jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}

				r = SetDB2JobData(hasuserid, jobData, KEY_SP_USER_ID, m_pDB->GetValue(0, 1));
				if(r == false)
				{
					LOG(LNOT, "Service Product Root exist. But User Information difference(sp_user_id)[J:%s].[J:%s,J:%s]",
						jobData[KEY_SP_USER_ID].c_str(), jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}
			}
		}
		else if ( m_pDB->GetNoTuples() > 1)
		{
			r = false;
			LOG(LNOT, "Service Product Root duplicate.[J:%s,J:%s]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}
		else
		{
			exist = false;
			LOG(LDBG, "Service Root empty.[J:%s,J:%s]", 
				jobData[KEY_SP_SVC_TRAN_ID].c_str(),jobData[KEY_SP_SVC_ID].c_str());
		}

		if( r && exist )
		{
			LOG(LDBG, "Service Product Root exist.[%s,%s]", 
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}

		m_pDB->PgClear();

		return r;
	}

	return false;
}

bool CRCDBControl::CheckParentDir(CJobDataMap & jobData, bool & IgnoreCase)
{

	CJobDataMap parent;
	parent[KEY_SP_USER_SEQ] = jobData[KEY_SP_USER_SEQ];
	parent[KEY_SP_SVC_TRAN_ID] = jobData[KEY_SP_SVC_TRAN_ID];
	parent[KEY_REQ_URI] = p_name(jobData[KEY_REQ_URI]);

	// root
	if (parent[KEY_REQ_URI].empty()) {
		jobData[KEY_URI_PARENT].append("/");
		jobData[KEY_URI_PARENT].append(jobData[KEY_SP_SVC_TRAN_ID]);
		return true;
	}
		
	if (!GetFileInfo(parent, IgnoreCase)) {
		LOG(LERR, "Check the parent path failure.[%s,%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_REQ_URI].c_str());
		return false;
	}
		
	if (parent[KEY_HOST_NAME].size())
		jobData[KEY_URI_PARENT] = parent[KEY_URI];

	return true;
}

string	CRCDBControl::InsertStr(CJobDataMap & jobData, const char* key, int index, const char **paramValues)
{
	ostringstream sql;

	string key2 = key;

	if(key2.compare(PRODUCT_EXT_AUTH_MODE_STR) == 0) 
		key2 = "mode";
	else if (key2.compare(PRODUCT_BAND_MODE_STR) == 0) 
		key2 = "mode";
	else if (key2.compare("display_name") == 0)
	{
		// 2014.07.23 신규 형상(9.3) 경우 대소문자 구분 기능을 display_name 사용하므로
		// 관련 값을 uri 와 동일 하게 셋팅한다.
		if (!jobData[KEY_URI].empty())
		{
			paramValues[index] = jobData[KEY_URI].c_str();
			sql << key2;
		}
	}
	else 
		key2 = key;

	if(!jobData[key].empty())
	{
		paramValues[index] = jobData[key].c_str();
		sql << key2;
	}

	_LOG(LDBG, "InsertStr :%d,%s,%s", index, key, sql.str().c_str());

	return sql.str();
}

string	CRCDBControl::UpdateStr(CJobDataMap & jobData, const char* key, int index, const char **paramValues)
{
	ostringstream sql;

	string key2 = key;

	if(key2.compare(PRODUCT_EXT_AUTH_MODE_STR) == 0) 
		key2 = "mode";
	else if (key2.compare(PRODUCT_BAND_MODE_STR) == 0) 
		key2 = "mode";
	else 
		key2 = key;

	if(!jobData[key].empty())
	{
		paramValues[index] = jobData[key].c_str();
		sql << key2 << " = $" << (index+1);
	}

	_LOG(LDBG, "UpdateStr :%d,%s,%s", index, key, sql.str().c_str());

	return sql.str();
}

string	CRCDBControl::UpdateStr(CJobDataMap & jobData, const char* key)
{
	ostringstream sql;

	string key2 = key;

	if(key2.compare(PRODUCT_EXT_AUTH_MODE_STR) == 0) 
		key2 = "mode";
	else if (key2.compare(PRODUCT_BAND_MODE_STR) == 0) 
		key2 = "mode";
	else 
		key2 = key;

	if(!jobData[key].empty())
	{
		sql << key2 << " = '" <<  jobData[key] << "'";
	}

	_LOG(LDBG, "UpdateStr :%s,%s", key, sql.str().c_str());

	return sql.str();
}

bool CRCDBControl::InsertUerInfo(CJobDataMap & jobData)
{
	// insert t_sms_sp_user
	int index = 0;
	const char *paramValues[3];

	ostringstream sql;

	sql << "INSERT INTO t_sms_sp_user "; 
	sql	<< "(";	

	sql << "reg_datetime,update_datetime";

	vector<string> cols;
	StringSplit(USER_INFO_INSERT_COLUMN, ",", cols);

	for (vector<string>::iterator it = cols.begin() ; it != cols.end(); ++it)
	{
		string s = InsertStr(jobData,  (*it).c_str(), index, paramValues);
		if(!s.empty())
		{
			sql << "," << s;
			++index;
		}
	}

	
	sql	<< ")";
	sql	<< " VALUES ";
	sql	<< "(";	
	// 2014-04-23 : dadamin
	// pgpool 경우 now 사용할 경우 세션이 비정상 종료 발생함
	//  	2014 - 04 - 23 19:01 : 12 ERROR : pid 13391 : Child process 12705 was terminated by segmentation fault
	// 		2014 - 04 - 23 19 : 09 : 43 LOG : pid 14018 : An adress "0x137a2c50" does not exist in memory pool.
	// sql	<< "NOW(),NOW()";		//reg_datetime,update_datetime
	sql << timeSQL(1);
	
	for(int i = 0; i < index; ++i)
	{
		sql	<< ",$"<<(i+1);
	}
	sql	<< ")";	

	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed user information insert.[J:%s,J:%s]",
			jobData[KEY_SP_USER_SEQ].c_str(), jobData[KEY_SP_USER_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::UpdateUserInfo(CJobDataMap & jobData)
{
	// update t_sms_sp_user
	int index = 0;
	const char *paramValues[19];

	ostringstream sql;

	sql << "UPDATE t_sms_sp_user SET ";
	// 2014-04-23 : dadamin
	// pgpool 경우 now 사용할 경우 세션이 비정상 종료 발생함
	//  	2014 - 04 - 23 19:01 : 12 ERROR : pid 13391 : Child process 12705 was terminated by segmentation fault
	// 		2014 - 04 - 23 19 : 09 : 43 LOG : pid 14018 : An adress "0x137a2c50" does not exist in memory pool.
	//sql << "update_datetime = NOW()";
	sql << timeSQL(2);

	// SET
	vector<string> cols;
	StringSplit(USER_INFO_UPDATE_COLUMN, ",", cols);

	for (vector<string>::iterator it = cols.begin() ; it != cols.end(); ++it)
	{
		string s = UpdateStr(jobData,  (*it).c_str(), index, paramValues);
		if(!s.empty())
		{
			sql << "," << s;
			++index;
		}
	}

	// WHERE 
	if(!jobData[KEY_SP_USER_ID].empty())
	{		
		paramValues [index++] = jobData[KEY_SP_USER_ID].c_str();
		sql << " WHERE sp_user_id = $" << index;
	}
	else
	{		
		paramValues [index++] = jobData[KEY_SP_USER_SEQ].c_str();
		sql << " WHERE sp_user_seq = $" << index;
	}


	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed user information update.[J:%s,J:%s]",
			jobData[KEY_SP_USER_SEQ].c_str(), jobData[KEY_SP_USER_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::DeleteUserInfo(CJobDataMap & jobData)
{
	// delete t_sms_sp_user
	int index = 0;
	const char *paramValues[19];

	ostringstream sql;

	sql << "DELETE FROM t_sms_sp_user ";
	
	// WHERE 
	if (!jobData[KEY_SP_USER_ID].empty())
	{
		paramValues[index++] = jobData[KEY_SP_USER_ID].c_str();
		sql << " WHERE sp_user_id = $" << index;
	}
	else
	{
		paramValues[index++] = jobData[KEY_SP_USER_SEQ].c_str();
		sql << " WHERE sp_user_seq = $" << index;
	}

	if (DoSetSQL(sql.str(), index, paramValues))
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed user information delete.[J:%s,J:%s]",
			jobData[KEY_SP_USER_SEQ].c_str(), jobData[KEY_SP_USER_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::SetUserInfo(CJobDataMap & jobData,  bool & exist)
{
	// set t_sms_sp_user
	bool r = true;

	if (exist)
	{
		if (jobData[KEY_DEL_USER_INFO].compare("Y") == 0)
			r = DeleteUserInfo(jobData);
		else
			r = UpdateUserInfo(jobData);
	}		
	else 
		r = InsertUerInfo(jobData);

	return r;
}

bool CRCDBControl::InsertProductInfo(CJobDataMap & jobData)
{	
	// insert t_sms_sp_svc_product
	int index = 0;
	const char *paramValues[19];

	ostringstream sql;

	sql << "INSERT INTO t_sms_sp_svc_product "; 
	sql	<< "(";	

	sql << "reg_datetime,update_datetime";

	vector<string> cols;
	StringSplit(PRODUCT_INSERT_COLUMN, ",", cols);

	for (vector<string>::iterator it = cols.begin() ; it != cols.end(); ++it)
	{
		string s = InsertStr(jobData,  (*it).c_str(), index, paramValues);
		if(!s.empty())
		{
			sql << "," << s;
			++index;
		}
	}
		
	sql	<< ")";
	sql	<< " VALUES ";
	sql	<< "(";	
	// 2014-04-23 : dadamin
	// pgpool 경우 now 사용할 경우 세션이 비정상 종료 발생함
	//  	2014 - 04 - 23 19:01 : 12 ERROR : pid 13391 : Child process 12705 was terminated by segmentation fault
	// 		2014 - 04 - 23 19 : 09 : 43 LOG : pid 14018 : An adress "0x137a2c50" does not exist in memory pool.
	// sql	<< "NOW(),NOW()";		//reg_datetime,update_datetime
	sql << timeSQL(1);

	for(int i = 0; i < index; ++i)
	{
		sql	<< ",$"<<(i+1);
	}
	sql	<< ")";	
	
	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service product insert.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::UpdateProductInfo(CJobDataMap & jobData)
{
	// update t_sms_sp_svc_product
	int index = 0;
	const char *paramValues[19];

	ostringstream sql;

	sql << "UPDATE t_sms_sp_svc_product SET ";
	// 2014-04-23 : dadamin
	// pgpool 경우 now 사용할 경우 세션이 비정상 종료 발생함
	//  	2014 - 04 - 23 19:01 : 12 ERROR : pid 13391 : Child process 12705 was terminated by segmentation fault
	// 		2014 - 04 - 23 19 : 09 : 43 LOG : pid 14018 : An adress "0x137a2c50" does not exist in memory pool.
	//sql << "update_datetime = NOW()";
	sql << timeSQL(2);


	// SET
	vector<string> cols;
	StringSplit(PRODUCT_UPDATE_COLUMN, ",", cols);

	for (vector<string>::iterator it = cols.begin() ; it != cols.end(); ++it)
	{
		string s;
		s = UpdateStr(jobData,  (*it).c_str(), index, paramValues);
		if(!s.empty())
		{
			sql << "," << s;
			++index;
		}
	}

	// WHERE 
	if(!jobData[KEY_SP_SVC_TRAN_ID].empty())
	{		
		paramValues [index++] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
		sql << " WHERE sp_svc_tran_id = $" << index;
	}
	else
	{		
		paramValues [index++] = jobData[KEY_SP_SVC_ID].c_str();
		sql << " WHERE sp_svc_id = $" << index;
	}


	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service product update.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::DeleteProductInfo(CJobDataMap & jobData)
{
	// delete t_sms_sp_svc_product
	int index = 0;
	const char *paramValues[19];

	ostringstream sql;

	sql << "DELETE FROM t_sms_sp_svc_product ";

	// WHERE 
	if (!jobData[KEY_SP_SVC_TRAN_ID].empty())
	{
		paramValues[index++] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
		sql << " WHERE sp_svc_tran_id = $" << index;
	}
	else
	{
		paramValues[index++] = jobData[KEY_SP_SVC_ID].c_str();
		sql << " WHERE sp_svc_id = $" << index;
	}
	
	if (DoSetSQL(sql.str(), index, paramValues))
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service product delete.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::SetProductInfo(CJobDataMap & jobData, bool & exist)
{
	// set t_sms_sp_svc_product
	bool r = true;

	if (exist)
	{
		if (jobData[KEY_DEL_PRODUCT].compare("Y") == 0)
			r = DeleteProductInfo(jobData);
		else 
			r = UpdateProductInfo(jobData);
	}		
	else
		r = InsertProductInfo(jobData);

	return r;
}

bool CRCDBControl::InsertProductExtAuth(CJobDataMap & jobData)
{
	// insert t_sms_sp_svc_product_val
	int index = 0;
	const char *paramValues[19];

	ostringstream sql;

	sql << "INSERT INTO t_sms_sp_svc_product_val "; 
	sql	<< "(";	

	sql << "reg_datetime,update_datetime";

	vector<string> cols;
	StringSplit(PRODUCT_EXT_AUTH_INSERT_COLUMN, ",", cols);

	for (vector<string>::iterator it = cols.begin() ; it != cols.end(); ++it)
	{
		string s = InsertStr(jobData,  (*it).c_str(), index, paramValues);
		if(!s.empty())
		{
			sql << "," << s;
			++index;
		}
	}

	_LOG(LDBG, "InsertProductExtAuth : insert itme cnt=%d", index);
	if ( index < 3 )
	{
		LOG(LWAR, "There is no data to be inserted"); 
		return true;
	}

	sql	<< ")";
	sql	<< " VALUES ";
	sql	<< "(";	
	// 2014-04-23 : dadamin
	// pgpool 경우 now 사용할 경우 세션이 비정상 종료 발생함
	//  	2014 - 04 - 23 19:01 : 12 ERROR : pid 13391 : Child process 12705 was terminated by segmentation fault
	// 		2014 - 04 - 23 19 : 09 : 43 LOG : pid 14018 : An adress "0x137a2c50" does not exist in memory pool.
	// sql	<< "NOW(),NOW()";		//reg_datetime,update_datetime
	sql << timeSQL(1);

	for(int i = 0; i < index; ++i)
	{
		sql	<< ",$"<<(i+1);
	}
	sql	<< ")";	

	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service product extensible authentication insert.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::UpdateProductExtAuth(CJobDataMap & jobData)
{
	// update t_sms_sp_svc_product_val
	int index = 0;
	const char *paramValues[19];

	ostringstream sql;

	sql << "UPDATE t_sms_sp_svc_product_val SET ";
	// 2014-04-23 : dadamin
	// pgpool 경우 now 사용할 경우 세션이 비정상 종료 발생함
	//  	2014 - 04 - 23 19:01 : 12 ERROR : pid 13391 : Child process 12705 was terminated by segmentation fault
	// 		2014 - 04 - 23 19 : 09 : 43 LOG : pid 14018 : An adress "0x137a2c50" does not exist in memory pool.
	//sql << "update_datetime = NOW()";
	sql << timeSQL(2);


	// SET
	vector<string> cols;
	StringSplit(PRODUCT_EXT_AUTH_UPDATE_COLUMN, ",", cols);

	for (vector<string>::iterator it = cols.begin() ; it != cols.end(); ++it)
	{
		string s = UpdateStr(jobData,  (*it).c_str(), index, paramValues);
		if(!s.empty())
		{
			sql << "," << s;
			++index;
		}
	}

	// WHERE 
	if(!jobData[KEY_SP_SVC_TRAN_ID].empty())
	{		
		paramValues [index++] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
		sql << " WHERE sp_svc_tran_id = $" << index;
	}
	else
	{		
		paramValues [index++] = jobData[KEY_SP_SVC_ID].c_str();
		sql << " WHERE sp_svc_id = (SELECT sp_svc_tran_id FROM t_sms_sp_svc_product WHERE sp_svc_id =$" 
			<< index << ")";
	}


	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service product extensible authentication update.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::DeleteProductExtAuth(CJobDataMap & jobData)
{
	// update t_sms_sp_svc_product_val
	int index = 0;
	const char *paramValues[3];

	ostringstream sql;

	sql << "DELETE FROM t_sms_sp_svc_product_val";

	// WHERE 
	if(!jobData[KEY_SP_SVC_TRAN_ID].empty())
	{		
		paramValues [index++] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
		sql << " WHERE sp_svc_tran_id = $" << index;
	}
	else
	{		
		paramValues [index++] = jobData[KEY_SP_SVC_ID].c_str();
		sql << " WHERE sp_svc_id = (SELECT sp_svc_tran_id FROM t_sms_sp_svc_product WHERE sp_svc_id = $" 
			<< index << ")";
	}

	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service product extensible authentication deleted.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::SetProductExtAuth(CJobDataMap & jobData, bool & exist)
{
	// set t_sms_sp_svc_product_val
	bool r = true;

	if(exist)
	{
		if(jobData[KEY_VALIDATE_SP_SESSION_ID_YN].compare("N") == 0)
			r = DeleteProductExtAuth(jobData);
		else
			r = UpdateProductExtAuth(jobData);
	}
	else
	{
		if(jobData[KEY_VALIDATE_SP_SESSION_ID_YN].compare("Y") == 0)
			r = InsertProductExtAuth(jobData);
	}

	return r;
}

bool CRCDBControl::InsertProductBand(CJobDataMap & jobData)
{
	// insert t_sms_sp_svc_product_band
	int index = 0;
	const char *paramValues[19];

	ostringstream sql;

	sql << "INSERT INTO t_sms_sp_svc_product_band "; 
	sql	<< "(";	

	sql << "reg_datetime,update_datetime";

	vector<string> cols;
	StringSplit(PRODUCT_BAND_INSERT_COLUMN, ",", cols);

	for (vector<string>::iterator it = cols.begin() ; it != cols.end(); ++it)
	{
		string s = InsertStr(jobData,  (*it).c_str(), index, paramValues);
		if(!s.empty())
		{
			sql << "," << s;
			++index;
		}
	}

	_LOG(LDBG, "InsertProductBand : insert itme cnt=%d", index);
	if ( index < 3 )
	{
		LOG(LWAR, "There is no data to be inserted"); 
		return true;
	}

	sql	<< ")";
	sql	<< " VALUES ";
	sql	<< "(";	
	// 2014-04-23 : dadamin
	// pgpool 경우 now 사용할 경우 세션이 비정상 종료 발생함
	//  	2014 - 04 - 23 19:01 : 12 ERROR : pid 13391 : Child process 12705 was terminated by segmentation fault
	// 		2014 - 04 - 23 19 : 09 : 43 LOG : pid 14018 : An adress "0x137a2c50" does not exist in memory pool.
	// sql	<< "NOW(),NOW()";		//reg_datetime,update_datetime
	sql << timeSQL(1);

	for(int i = 0; i < index; ++i)
	{
		sql	<< ",$"<<(i+1);
	}
	sql	<< ")";	

	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service product bandwidth insert.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::UpdateProductBand(CJobDataMap & jobData)
{
	// update t_sms_sp_svc_product_band
	int index = 0;
	const char *paramValues[19];

	ostringstream sql;

	sql << "UPDATE t_sms_sp_svc_product_band SET ";
	// 2014-04-23 : dadamin
	// pgpool 경우 now 사용할 경우 세션이 비정상 종료 발생함
	//  	2014 - 04 - 23 19:01 : 12 ERROR : pid 13391 : Child process 12705 was terminated by segmentation fault
	// 		2014 - 04 - 23 19 : 09 : 43 LOG : pid 14018 : An adress "0x137a2c50" does not exist in memory pool.
	//sql << "update_datetime = NOW()";
	sql << timeSQL(2);


	// SET
	vector<string> cols;
	StringSplit(PRODUCT_BAND_UPDATE_COLUMN, ",", cols);

	for (vector<string>::iterator it = cols.begin() ; it != cols.end(); ++it)
	{
		string s = UpdateStr(jobData,  (*it).c_str(), index, paramValues);
		if(!s.empty())
		{
			sql << "," << s;
			++index;
		}
	}

	// WHERE 
	if(!jobData[KEY_SP_SVC_TRAN_ID].empty())
	{		
		paramValues [index++] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
		sql << " WHERE sp_svc_tran_id = $" << index;
	}
	else
	{		
		paramValues [index++] = jobData[KEY_SP_SVC_ID].c_str();
		sql << " WHERE sp_svc_id = (SELECT sp_svc_tran_id FROM t_sms_sp_svc_product WHERE sp_svc_id =$" 
			<< index << ")";
	}


	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service product bandwidth update.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}
	return true;
}

bool CRCDBControl::DeleteProductBand(CJobDataMap & jobData)
{
	// update t_sms_sp_svc_product_band
	int index = 0;
	const char *paramValues[3];

	ostringstream sql;

	sql << "DELETE FROM t_sms_sp_svc_product_band";

	// WHERE 
	if(!jobData[KEY_SP_SVC_TRAN_ID].empty())
	{		
		paramValues [index++] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
		sql << " WHERE sp_svc_tran_id = $" << index;
	}
	else
	{		
		paramValues [index++] = jobData[KEY_SP_SVC_ID].c_str();
		sql << " WHERE sp_svc_id = (SELECT sp_svc_tran_id FROM t_sms_sp_svc_product WHERE sp_svc_id =$" 
			<< index << ")";
	}


	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service product bandwidth deleted.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}
	return true;
}

bool CRCDBControl::SetProductBand(CJobDataMap & jobData, bool & exist)
{
	// set t_sms_sp_svc_product_band
	bool r = true;

	if(exist)
	{
		if( jobData[KEY_BANDWIDTH_CTRL_YN].compare("N") == 0 )
			r = DeleteProductBand(jobData);
		else 
			r = UpdateProductBand(jobData);
	}
	else
	{
		if( jobData[KEY_BANDWIDTH_CTRL_YN].compare("Y") == 0 )
			r = InsertProductBand(jobData);
	}

	return r;
}

bool CRCDBControl::GetSyncLink(CJobDataMap & jobData)
{
	ostringstream sql;

	const char *paramValues[4];
	int index = 0;

	sql << "SELECT sp_svc_tran_id, master_yn, linked_sp_svc_tran_id, linked_rcts ";
	sql << "FROM t_sms_sp_svc_product_sync ";
	sql << "WHERE ";

	paramValues[index++] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
	sql << "sp_svc_tran_id = $" << index << " ";

	if (jobData[KEY_LINK_MASTER_YN].size())
	{
		paramValues[index++] = jobData[KEY_LINK_MASTER_YN].c_str();
		sql << "AND master_yn = $" << index << " ";
	}

	if (jobData[KEY_LINK_SP_SVC_TRAN_ID].size())
	{
		paramValues[index++] = jobData[KEY_LINK_SP_SVC_TRAN_ID].c_str();
		sql << "AND linked_sp_svc_tran_id = $" << index << " ";
	}

	if (jobData[KEY_LINK_RCTS].size())
	{
		paramValues[index++] = jobData[KEY_LINK_RCTS].c_str();
		sql << "AND linked_rcts = $" << index << " ";
	}

	if (DoSQL(sql.str(), index, paramValues))
	{
		ostringstream d;
		for (int c = 0; c < m_pDB->GetNoTuples(); ++c)
		{
			if (c > 0) d << ",";
			d << m_pDB->GetValue(c, 0) << "|" << m_pDB->GetValue(c, 1) << "|";
			d << m_pDB->GetValue(c, 2) << "|" << m_pDB->GetValue(c, 3);
		}
		m_pDB->PgClear();

		jobData[KEY_SYNC_LIST] = d.str();

		return true;
	}

	return false;
}


bool CRCDBControl::InsertProductSync(CJobDataMap & jobData)
{
	// insert t_sms_sp_svc_product_sync
	int index = 0;
	const char *paramValues[19];

	if (jobData[KEY_LINK_SP_SVC_TRAN_ID].empty() 
		|| jobData[KEY_LINK_RCTS].empty()
		|| jobData[KEY_LINK_MASTER_YN].empty())
	{
		LOG(LWAR, "Sync Link Infomation empyt [J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return true;
	}

	ostringstream sql;

	sql << "INSERT INTO t_sms_sp_svc_product_sync ";
	sql << "(";

	vector<string> cols;
	StringSplit(PRODUCT_SYNC_INSERT_COLUMN, ",", cols);

	for (vector<string>::iterator it = cols.begin(); it != cols.end(); ++it)
	{
		string s = InsertStr(jobData, (*it).c_str(), index, paramValues);

		if (index > 0)
		{
			sql << ",";
		}

		if (!s.empty())
		{
			sql << s;
			++index;
		}
	}

	sql << ")";
	sql << " VALUES ";
	sql << "(";

	for (int i = 0; i < index; ++i)
	{
		if (i > 0)
		{
			sql << ",";
		}

		sql << "$" << (i + 1);
	}

	sql << ")";

	if (DoSetSQL(sql.str(), index, paramValues))
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service product sync insert.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::DeleteProductSync(CJobDataMap & jobData)
{
	// delete t_sms_sp_svc_product_sync
	int index = 0;
	const char *paramValues[19];

	/*
	if (jobData[KEY_LINK_SP_SVC_TRAN_ID].empty() || jobData[KEY_LINK_RCTS].empty())
	{
		LOG( LERR, "This item is not enough to delete the t_sms_sp_svc_product_sync Table.[J:%s, J:%s]", 
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}
	*/

	ostringstream sql;

	sql << "DELETE FROM t_sms_sp_svc_product_sync ";
	
	// WHERE 
	if (!jobData[KEY_SP_SVC_TRAN_ID].empty())
	{
		paramValues[index++] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
		sql << "WHERE sp_svc_tran_id = $" << index << " ";
	}
	else
	{
		paramValues[index++] = jobData[KEY_SP_SVC_ID].c_str();
		sql << "WHERE sp_svc_id = (SELECT sp_svc_tran_id FROM t_sms_sp_svc_product WHERE sp_svc_id = $"
			<< index << ") ";
	}

	if (!jobData[KEY_LINK_MASTER_YN].empty())
	{
		paramValues[index++] = jobData[KEY_LINK_MASTER_YN].c_str();
		sql << "AND master_yn = $" << index << " ";
	}

	if (!jobData[KEY_LINK_SP_SVC_TRAN_ID].empty())
	{
		paramValues[index++] = jobData[KEY_LINK_SP_SVC_TRAN_ID].c_str();
		sql << "AND linked_sp_svc_tran_id = $" << index << " ";
	}

	if (!jobData[KEY_LINK_RCTS].empty())
	{
		paramValues[index++] = jobData[KEY_LINK_RCTS].c_str();
		sql << "AND linked_rcts = $" << index << " ";
	}

	if (DoSetSQL(sql.str(), index, paramValues))
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service product sync deleted.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}
	
	return true;
}

bool CRCDBControl::SetProductSync(CJobDataMap & jobData, bool & exist)
{
	// set t_sms_sp_svc_product_sync
	bool r = true;

	if (exist)
	{
		if (jobData[KEY_REQ_LINK_CODE] == SYNC_LINK_CODE_UNLINK)
			r = DeleteProductSync(jobData);
	}
	else
	{
		if ( jobData[KEY_JOB_TYPE] == JOB_SERVICE_OPEN  
			|| jobData[KEY_REQ_LINK_CODE] == SYNC_LINK_CODE_LINK)
			r = InsertProductSync(jobData);
	}

	return r;
}

bool CRCDBControl::InsertUseDir(CJobDataMap & jobData)
{
	// insert t_dav_use_dir
	int index = 0;
	const char *paramValues[19];

	ostringstream sql;

	jobData["depth"] = "0";
	ostringstream uri;
	uri << "/" << jobData[KEY_SP_SVC_TRAN_ID];
	jobData["path_name"] = uri.str();

	sql << "INSERT INTO t_dav_use_dir ";
	sql << "(";
	vector<string> cols;
	StringSplit(SERVICE_VOLUME_INSERT_COLUMN, ",", cols);

	for (vector<string>::iterator it = cols.begin(); it != cols.end(); ++it)
	{
		if (index > 0)
			sql << ",";

		string s = InsertStr(jobData, (*it).c_str(), index, paramValues);
		if (!s.empty())
		{
			sql << s;
			++index;
		}
	}

	_LOG(LDBG, "InsertUseDir : insert itme cnt=%d", index);

	sql << ")";
	sql << " VALUES ";
	sql << "(";

	for (int i = 0; i < index; ++i)
	{
		if (i > 0)
			sql << ",";
		sql << "$" << (i + 1);
	}
	sql << ")";

	if (DoSetSQL(sql.str(), index, paramValues))
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service volume info insert.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::DeleteUseDir(CJobDataMap & jobData)
{
	// delete t_dav_use_dir
	int index = 0;
	const char *paramValues[3];

	ostringstream sql;

	sql << "DELETE FROM t_dav_use_dir";

	// WHERE 
	if (!jobData[KEY_SP_SVC_TRAN_ID].empty())
	{
		paramValues[index++] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
		sql << " WHERE sp_svc_tran_id = $" << index;
	}
	else
	{
		paramValues[index++] = jobData[KEY_SP_SVC_ID].c_str();
		sql << " WHERE sp_svc_tran_id = (SELECT sp_svc_tran_id FROM t_sms_sp_svc_product WHERE sp_svc_id =$"
			<< index << ")";
	}


	if (DoSetSQL(sql.str(), index, paramValues))
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service volume info deleted.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::SetVolumeInfo(CJobDataMap & jobData, bool & exist)
{
	// set t_dav_use_dir
	bool r = true;
	if (!exist)
		r = InsertUseDir(jobData);
	else
	{
		if (jobData[KEY_DEL_DIR_USED].compare("Y") == 0)
			r = DeleteUseDir(jobData);
	}

	return r;
}

bool CRCDBControl::InsertRootInfo(CJobDataMap & jobData)
{
	// insert meta 
	int index = 0;
	const char *paramValues[19];

	// 2014.06.07 dadamin 
	// 형상(9.3) 변경으로 테이블명 변경
	string tblname;
	if (jobData[KEY_SP_SVC_TRAN_ID].size() <= 0)
	{
		LOG(LERR, "There is no information about the service requested(insert root - tran_id).");
		return false;
	}

	tblname = GetMataTableName(jobData[KEY_SP_SVC_TRAN_ID].c_str());
	
	ostringstream sql;

	uint64_t nowtime = GetTimeStamp();

	sql << "INSERT INTO " << tblname;
	sql	<< "(";	

	sql << "creation_date,get_lastmodified,file_lastmodified";	
	sql << ",filename_org,filename_hash,resource_type,depth";
	// 2014.07.14 사용되지 않는 컬럼 정리(get_content_language,get_etag,supported_lock,lock_discovery)
	sql << ",get_content_length,get_content_type";
	sql << ",source";
	
	vector<string> cols;
	StringSplit(SERVICE_ROOT_INSERT_COLUMN, ",", cols);

	for (vector<string>::iterator it = cols.begin() ; it != cols.end(); ++it)
	{
		string s = InsertStr(jobData,  (*it).c_str(), index, paramValues);
		if(!s.empty())
		{
			sql << "," << s;
			++index;
		}
	}

	// 2014.07.14 사용되지 않는 컬럼 정리(get_content_language,get_etag,supported_lock,lock_discovery)
	sql	<< ")";
	sql	<< " VALUES ";
	sql	<< "(";	
	sql	<< nowtime << "," << nowtime << "," << nowtime;
	sql	<< ",'','',1,0";
	sql	<< ",0,'httpd/unix-directory'";
	sql	<< ",0";

	for(int i = 0; i < index; ++i)
	{
		sql	<< ",$"<<(i+1);
	}
	sql	<< ")";	

	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service root insert.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}


	return true;
}

bool CRCDBControl::UpdateRootInfo(CJobDataMap & jobData)
{
	// update meta
	int index = 0;
	const char *paramValues[19];

	// 2014.06.07 dadamin 
	// 형상(9.3) 변경으로 테이블명 변경
	string tblname;
	if (jobData[KEY_SP_SVC_TRAN_ID].size() <= 0)
	{
		LOG(LERR, "There is no information about the service requested(update root - tran_id).");
		return false;
	}

	tblname = GetMataTableName(jobData[KEY_SP_SVC_TRAN_ID].c_str());

	ostringstream sql;

	uint64_t nowtime = GetTimeStamp();

	sql << "UPDATE " << tblname << " SET "
		<< "get_lastmodified = " << nowtime;

	// SET
	vector<string> cols;
	StringSplit(SERVICE_ROOT_UPDATE_COLUMN, ",", cols);

	for (vector<string>::iterator it = cols.begin() ; it != cols.end(); ++it)
	{
		string s = UpdateStr(jobData,  (*it).c_str(), index, paramValues);
		if(!s.empty())
		{
			sql << "," << s;
			++index;
		}
	}

	// WHERE 
	if(!jobData[KEY_SP_SVC_TRAN_ID].empty())
	{		
		paramValues [index++] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
		sql << " WHERE sp_svc_tran_id = $" << index;
	}
	else
	{		
		paramValues [index++] = jobData[KEY_URI].c_str();
		sql << " WHERE uri = $" << index;
	}
	sql << " AND depth = 0 AND deleted_yn = 'N'";


	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service root update.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::DeleteRootInfo(CJobDataMap & jobData)
{
	// delete meta
	int index = 0;
	const char *paramValues[19];

	// 2014.06.07 dadamin 
	// 형상(9.3) 변경으로 테이블명 변경
	string tblname;
	if (jobData[KEY_SP_SVC_TRAN_ID].size() <= 0)
	{
		LOG(LERR, "There is no information about the service requested(delete root - tran_id).");
		return false;
	}

	tblname = GetMataTableName(jobData[KEY_SP_SVC_TRAN_ID].c_str());
	
	ostringstream sql;

	uint64_t nowtime = GetTimeStamp();

	sql << "DELETE FROM " << tblname;

	// WHERE 
	if(!jobData[KEY_SP_SVC_TRAN_ID].empty())
	{		
		paramValues [index++] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
		sql << " WHERE sp_svc_tran_id = $" << index;
	}
	else
	{		
		paramValues [index++] = jobData[KEY_URI].c_str();
		sql << " WHERE uri = $" << index;
	}
	sql << " AND depth = 0 AND deleted_yn = 'N'";


	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service root delete.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::SetRootInfo(CJobDataMap & jobData, bool & exist)
{
	// set meta - root

	bool r = true;

	if(exist)
	{
		if (jobData[KEY_DEL_ROOT].compare("Y") == 0)
		{
			r = DeleteRootInfo(jobData);
			// 2014-06-24 dadamin
			// 신규 형상(9.3) 경우 서비스별 메타 테이블 생성이므로 root 정보 삭제 성공 시 
			// 해당 테이블 삭제한다.
			if (r)
				r = DropMetaTable(jobData);
		}
		else 
			r = UpdateRootInfo(jobData);
	}
	else
	{
		if (jobData["host_name"].empty())
		{
			if (!jobData[KEY_SP_SVC_ID].empty())
			{
				ostringstream domain;
				domain << jobData[KEY_SP_SVC_ID] << "." <<
					CMyConfig::GetInstance()->GetRCDomain();
				jobData["host_name"] = domain.str();
			}
		}

		if (jobData[KEY_URI].empty())
		{
			if (!jobData[KEY_SP_SVC_TRAN_ID].empty())
			{
				ostringstream uri;
				uri << "/" << jobData[KEY_SP_SVC_TRAN_ID];
				jobData[KEY_URI] = uri.str();
			}
		}

		r = InsertRootInfo(jobData);
	}

	return r;
}

bool CRCDBControl::GetVolumeInformation(CJobDataMap & jobData)
{
	bool r = true;
		
	// check ignore case
	bool ignorecase = false;
	if (CheckUriIgnoreCase(jobData, ignorecase) == false)
	{
		return false;
	}

	const char *paramValues[3];
	ostringstream sql;

	sql << "SELECT d.sp_user_seq, d.sp_svc_tran_id, d.path_name, P.max_str_size, SUM(d.dir_used) "
		<< "FROM t_dav_use_dir AS d "
		<< " RIGHT OUTER JOIN t_sms_sp_svc_product AS P ON d.sp_svc_tran_id = P.sp_svc_tran_id";

	sql << " WHERE P.sp_svc_tran_id = $1";
	paramValues[0] = jobData[KEY_SP_SVC_TRAN_ID].c_str();

	if(jobData[KEY_REQ_URI].empty())
	{
		ostringstream uri;
		uri << "/" << jobData[KEY_SP_SVC_TRAN_ID];
		jobData[KEY_REQ_URI] = uri.str();
		
		if (ignorecase)
		{
			if (m_usedisplay)
				sql << " AND (d.path_name = lower($2) OR d.path_name ISNULL)";
			else
				sql << " AND (lower(d.path_name) = lower($2) OR d.path_name ISNULL)";
		}			
		else 
			sql << " AND (d.path_name = $2 OR d.path_name ISNULL)";		
	}
	else 
	{
		if (ignorecase)
		{
			if (m_usedisplay)
				sql << " AND d.path_name = lower($2)";
			else 
				sql << " AND lower(d.path_name) = lower($2)";
		}
		else
			sql << " AND d.path_name = $2";
	}

	sql << " GROUP BY d.sp_user_seq, d.sp_svc_tran_id, d.path_name, P.max_str_size ";

	paramValues[1] = jobData[KEY_REQ_URI].c_str();

	LOG(LDBG, "GetVolumeInformation %s,%s", paramValues[0], paramValues[1]);
	if( DoSQL(sql.str(), 2, paramValues) )
	{
		r = true;
		if( m_pDB->GetNoTuples() == 1 )
		{
			jobData[KEY_MAX_STR_SIZE] = m_pDB->GetValue(0, 3);
			jobData[KEY_DIR_USED] = m_pDB->GetValue(0, 4);
		}
		else if ( m_pDB->GetNoTuples() > 1 )
		{
			LOG(LNOT, "Volume Information duplicate.[J:%s,J:%s]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_REQ_URI].c_str());

			jobData[KEY_MAX_STR_SIZE] = m_pDB->GetValue(0, 3);
			jobData[KEY_DIR_USED] = m_pDB->GetValue(0, 4);
		}
		else 
		{
			LOG(LNOT, "Volume Information empty.[J:%s,J:%s]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_REQ_URI].c_str());

			jobData[KEY_MAX_STR_SIZE] = "0";
			jobData[KEY_DIR_USED] = "0" ;
		}
		m_pDB->PgClear();
	}
	else 
	{
		r = false;
	}

	if(r)
	{
		LOG(LDBG, "GetVolumeInformation : %s,%s|%s,%s", 
					jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_REQ_URI].c_str(),
					jobData[KEY_MAX_STR_SIZE].c_str(), jobData[KEY_DIR_USED].c_str());
	}

	return r;
}

bool CRCDBControl::GetAnonyDir(CJobDataMap & jobData, string targeturi, vector<string> & rdata)
{
	bool r = true;

	int ncnt = 0;
	const char *paramValues[3];
	ostringstream sql;

	sql << "SELECT sp_user_seq, sp_svc_tran_id, uri FROM t_dav_anonymous";
	sql << " WHERE sp_user_seq = $1 AND sp_svc_tran_id = $2 ";

	paramValues[ncnt++] = jobData[KEY_SP_USER_SEQ].c_str();
	paramValues[ncnt++] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
	 
	if( !targeturi.empty() )
	{
		sql << " AND uri = $3";
		paramValues[ncnt++] = targeturi.c_str();
	}

	if( DoSQL(sql.str(), ncnt, paramValues) )
	{
		r = true;
		// 결과 Row 수 확인
		int nNum = m_pDB->GetNoTuples();

		ostringstream response;
		char d = SDK_DELIMITER;
		for(int i = 0; i < nNum; ++i)
		{
			rdata.push_back(m_pDB->GetValue(i, 2));
			if(i > 0)
				response << d;
			response << m_pDB->GetValue(i, 2);
		}
		jobData[KEY_RES_URI] = response.str();
		m_pDB->PgClear();
	}
	else 
		r = false;

	return r;
}

bool CRCDBControl::InsertAnonymous(CJobDataMap & jobData, string &targeturi)
{
	if(targeturi.empty())
	{
		LOG(LERR, "Target uri is empty.[%s]", targeturi.c_str());
		return false;
	}

	jobData[KEY_URI] = targeturi;

	int index = 0;
	const char *paramValues[5];
	ostringstream sql;
	
	sql << "INSERT INTO t_dav_anonymous "; 
	sql	<< "(";	
	sql << "reg_datetime,update_datetime";

	vector<string> cols;
	StringSplit(ANONYMOUS_INSERT_COLUMN, ",", cols);

	for (vector<string>::iterator it = cols.begin() ; it != cols.end(); ++it)
	{
		string s = InsertStr(jobData,  (*it).c_str(), index, paramValues);
		if(!s.empty())
		{
			sql << "," << s;
			++index;
		}
	}

	sql	<< ")";
	sql	<< " VALUES ";
	sql	<< "(";	
	// 2014-04-23 : dadamin
	// pgpool 경우 now 사용할 경우 세션이 비정상 종료 발생함
	//  	2014 - 04 - 23 19:01 : 12 ERROR : pid 13391 : Child process 12705 was terminated by segmentation fault
	// 		2014 - 04 - 23 19 : 09 : 43 LOG : pid 14018 : An adress "0x137a2c50" does not exist in memory pool.
	// sql	<< "NOW(),NOW(),'N'";		//reg_datetime,update_datetime
	sql << timeSQL(1);
	sql << "";

	for(int i = 0; i < index; ++i)
	{
		sql	<< ",$"<<(i+1);
	}
	sql	<< ")";	

	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed Anonymous insert.[J:%s,J:%s]",
			jobData[KEY_SP_USER_SEQ].c_str(), jobData[KEY_SP_USER_ID].c_str());
		return false;
	}

	return true;
}

bool CRCDBControl::DeleteAnonymous(CJobDataMap & jobData, string &targeturi)
{
	int index = 0;
	const char *paramValues[3];
	ostringstream sql;

	sql << "DELETE FROM t_dav_anonymous WHERE "; 


	// WHERE 
	paramValues [index++] = jobData[KEY_SP_USER_SEQ].c_str();
	sql << KEY_SP_USER_SEQ << " = $" << index;
		
	paramValues [index++] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
	sql << " AND " << KEY_SP_SVC_TRAN_ID << " = $" << index;


	if(!targeturi.empty())
	{
		paramValues [index++] = targeturi.c_str();
		sql << " AND " << KEY_URI << " = $" << index;
	}
	
	if( DoSetSQL(sql.str(), index , paramValues) )
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed Anonymous delete.[J:%s,J:%s - %s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str(),
			targeturi.c_str());
		return false;
	}
	
	return true;
}

bool CRCDBControl::SetAnonyDir(CJobDataMap & jobData, string targeturi, bool isdel /* = false */)
{
	bool r = true;

	if(isdel)
		r = DeleteAnonymous(jobData, targeturi);
	else
		r = InsertAnonymous(jobData, targeturi);

	return r;
}

#define  SQLAND_STRING(index, sql)		if( index > 0 ) sql << " AND ";

string CRCDBControl::WhereStr(CJobDataMap & jobData, const char* key, int &index, const char **paramValues, bool IgnoreCase)
{
	ostringstream r;
	
	if(!jobData[key].empty())
	{
		SQLAND_STRING(index, r);
		if ( IgnoreCase )
			r << key << " = lower($" << (index + 1) << ")";
		else 
			r << key << " = $" << (index + 1) ;

		paramValues[index++] = jobData[key].c_str();
	}

	_LOG(LDBG, "WhereStr :%d,%s,%s,%s", index, key, 
		r.str().c_str(), jobData[key].c_str());

	return r.str();
}

bool CRCDBControl::GetFileInfo(CJobDataMap & jobData, bool IgnoreCase /*= false*/)
{
	bool r = true;

	if( jobData[KEY_REQ_URI].empty() ) 
	{
		LOG(LERR, "Request URI is empty.");
		return false;
	}

	// 2014.06.09 dadamin 
	// 형상(9.3) 변경으로 테이블명 변경
	string tblname;
	if (jobData[KEY_SP_SVC_TRAN_ID].size() <= 0)
	{
		LOG(LERR, "There is no information about the service requested(GetFileInfo - tran_id).");
		return false;
	}

	tblname = GetMataTableName(jobData[KEY_SP_SVC_TRAN_ID].c_str());

	string::size_type pos = jobData[KEY_REQ_URI].find_last_of("/");
	string::size_type len = jobData[KEY_REQ_URI].size();
	
	string ruri = jobData[KEY_REQ_URI];
	if (pos == 0 && len == 1)
	{
		// root
		ruri.clear();
	}
	else if ((pos + 1) == len)
	{
		// tail remove
		ruri = ruri.substr(0, pos);
	}
	else
	{
		// nothing
	}

	ostringstream uri;
	uri << "/" << jobData[KEY_SP_SVC_TRAN_ID] << ruri;
	jobData[KEY_URI] = uri.str();

	int index = 0;
	const char *paramValues[5];
	ostringstream sql;

	sql << "SELECT " ;
	sql << " sp_user_seq, sp_svc_tran_id, host_name, resource_type, uri";
	sql << ", filename_hash, depth, get_content_length, deleted_yn, is_cache";
	sql << ", file_lastmodified";
	sql << " FROM " << tblname;

	sql << " WHERE ";

	sql << WhereStr(jobData, KEY_SP_USER_SEQ, index, paramValues);
	sql << WhereStr(jobData, KEY_SP_SVC_TRAN_ID, index, paramValues);
	sql << WhereStr(jobData, KEY_URI, index, paramValues, IgnoreCase);

	SQLAND_STRING(index, sql); 
	sql << " deleted_yn = 'N' AND is_cache = 'N'";

	if( DoSQL(sql.str(), index, paramValues) )
	{	
		if( m_pDB->GetNoTuples() == 1 )
		{
			if(!jobData[KEY_GET_CONTENT_LENGTH].empty() &&
				jobData[KEY_GET_CONTENT_LENGTH].compare(m_pDB->GetValue(0, 7)) != 0)
			{
				r = false;
				LOG(LERR, "Differs from the requested file size and the size of the files in the meta.[J:%s]",
					jobData[KEY_REQ_URI].c_str());
			}
			else 
			{				
				jobData[KEY_HOST_NAME] = m_pDB->GetValue(0, 2);
				jobData[KEY_RESOURCE_TYPE] = m_pDB->GetValue(0, 3);
				jobData[KEY_FILENAME_HASH] = m_pDB->GetValue(0, 5);
				jobData[KEY_GET_CONTENT_LENGTH] = m_pDB->GetValue(0, 7);
			}
		}
		else if ( m_pDB->GetNoTuples() > 1 )
		{
			r = false;
			LOG(LERR, "File Information duplicate.[J:%s]", jobData[KEY_REQ_URI].c_str());
		}
		else 
		{
			r = true;
			_LOG(LNOT, "File Information empty.[J:%s]", jobData[KEY_REQ_URI].c_str());		
		}
		
		m_pDB->PgClear();
	}
	else 
		r = false;
		
	return r;
}

bool CRCDBControl::HasFile(CJobDataMap & jobData, bool & exist)
{
	bool r = true;

	// 2014.06.09 dadamin 
	// 형상(9.3) 변경으로 테이블명 변경
	string tblname;
	if (jobData[KEY_SP_SVC_TRAN_ID].size() <= 0)
	{
		LOG(LERR, "There is no information about the service requested(HasFile - tran_id).");
		return false;
	}

	tblname = GetMataTableName(jobData[KEY_SP_SVC_TRAN_ID].c_str());

	ostringstream uri;
	uri << "/" << jobData[KEY_SP_SVC_TRAN_ID] << "/";
	jobData[KEY_URI] = uri.str();
	
	const char *paramValues[1];
	ostringstream sql;

	sql << "SELECT uri FROM " << tblname <<" WHERE uri LIKE $1 || '%' LIMIT 1";
	paramValues[0] = jobData[KEY_URI].c_str();

	if (DoSQL(sql.str(), 1, paramValues))
	{
		r = true;
		if (m_pDB->GetNoTuples() > 0)
		{
			exist = true;
			LOG(LINF, "File Information exist.[uri:%s]", paramValues[0]);
		}
		else
		{
			exist = false;
			LOG(LINF, "File Information empty.[uri:%s]", paramValues[0]);
		}
		m_pDB->PgClear();
	}
	else
		r = false;
	
	return r;
}

// 2014.06.07 dadamin
// 메타 테이블명 반환
string	CRCDBControl::GetMataTableName(const char* tranid)
{
	string r;

	switch (m_tabletype)
	{
	case 1:
		r = "t_meta_";
		r += tranid;
		break;
	case 0:
	default:
		r = "t_dav_resource";
		break;
	}

	LOG(LDBG, "Working Table Name %s", r.c_str());

	return r;
}

bool CRCDBControl::CheckUriIgnoreCase(CJobDataMap & jobData, bool & IgnoreCase)
{
	bool hasuserseq = true, hasuserid = true;
	bool hastranid = true, hassvcid = true;

	CheckJobDataUserInfo(jobData, hasuserseq, hasuserid);

	if (CheckJobDataSvcProduct(jobData, hastranid, hassvcid) == false)
	{
		LOG(LERR, "Service Procuct(uir ignore case) Jobdata empty.(ALL)");
		return false;
	}

	int i = 0;
	const char *paramValues[2];
	ostringstream sql;

	sql << "SELECT U.sp_user_seq, U.sp_user_id, P.sp_svc_tran_id, P.sp_svc_id "
		<< ", P.uri_ignore_case "
		<< "FROM t_sms_sp_svc_product AS P "
		<< "LEFT OUTER JOIN  t_sms_sp_user AS U ON P.sp_user_seq = U.sp_user_seq";

	if (hastranid && hassvcid)
	{
		i = 2;
		sql << " WHERE P.sp_svc_tran_id = $1 OR P.sp_svc_id = $2";
		paramValues[0] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
		paramValues[1] = jobData[KEY_SP_SVC_ID].c_str();
	}
	else if (hastranid)
	{
		i = 1;
		sql << " WHERE P.sp_svc_tran_id = $1";
		paramValues[0] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
	}
	else
	{
		i = 1;
		sql << " WHERE P.sp_svc_id = $1";
		paramValues[0] = jobData[KEY_SP_SVC_ID].c_str();
	}

	if (DoSQL(sql.str(), i, paramValues))
	{
		bool r = true, exist = false;
		if (m_pDB->GetNoTuples() == 1)
		{
			if (strlen(m_pDB->GetValue(0, 0)) == 0)
			{
				r = false;
				LOG(LNOT, "Service Product exist. But User Information empty.[J:%s,J:%s]",
					jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
			}
			else
			{
				r = SetDB2JobData(hassvcid, jobData, KEY_SP_SVC_ID, m_pDB->GetValue(0, 3));
				if (r == false)
				{
					LOG(LNOT, "Service Product difference(%s).[J:%s,D:%s]", KEY_SP_SVC_ID
						, jobData[KEY_SP_SVC_ID].c_str(), m_pDB->GetValue(0, 3));
				}
				else
				{
					r = SetDB2JobData(hastranid, jobData, KEY_SP_SVC_TRAN_ID, m_pDB->GetValue(0, 2));
					if (r == false)
					{
						LOG(LNOT, "Service Product difference(%s).[J:%s,D:%s]", KEY_SP_SVC_TRAN_ID
							, jobData[KEY_SP_SVC_TRAN_ID].c_str(), m_pDB->GetValue(0, 2));
					}
				}

				if (r) exist = true;
			}

			if (r && exist)
			{
				r = SetDB2JobData(hasuserseq, jobData, KEY_SP_USER_SEQ, m_pDB->GetValue(0, 0));
				if (r == false)
				{
					LOG(LNOT, "Service Product exist. But User Information difference(%s)[J:%s].[J:%s,J:%s]"
						, KEY_SP_USER_SEQ, jobData[KEY_SP_USER_SEQ].c_str(),
						jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}

				r = SetDB2JobData(hasuserid, jobData, KEY_SP_USER_ID, m_pDB->GetValue(0, 1));
				if (r == false)
				{
					LOG(LNOT, "Service Product exist. But User Information difference(%s)[J:%s].[J:%s,J:%s]"
						, KEY_SP_USER_ID, jobData[KEY_SP_USER_ID].c_str(),
						jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
				}

				string v = m_pDB->GetValue(0, 4);
				IgnoreCase = (v.compare("Y") == 0);
			}
		}
		else if (m_pDB->GetNoTuples() > 1)
		{
			r = false;
			LOG(LNOT, "Service Product duplicate.[J:%s,J:%s]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}
		else
		{
			exist = false;
			LOG(LDBG, "Service Product empty.[J:%s,J:%s]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		}

		if (r && exist)
		{
			LOG(LDBG, "Service Product exist.[%s,%s, %d]",
				jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str()
				, IgnoreCase);
		}

		m_pDB->PgClear();
		return r;
	}

	return true;
}

static uint64_t convert(string s)
{
	if (s.size() == 0)
		return 0;

	uint64_t v = 0;
	size_t i = 0;
	char sign = (s[0] == '-' || s[0] == '+') ? (++i, s[0]) : '+';
	for (; i < s.size(); ++i)
	{
		if (s[i] < '0' || s[i] > '9')
			return 0;
		v = v * 10 + s[i] - '0';
	}
	return sign == '-' ? -v : v;
}

bool CRCDBControl::GetTotalCntFiles(CJobDataMap & jobData, uint64_t & total, uint64_t limit /*= 0*/)
{
	bool r = true;

	string tblname;
	if (jobData[KEY_SP_SVC_TRAN_ID].size() <= 0)
	{
		LOG(LERR, "There is no information about the service requested(GetTotalCntFiles - tran_id).");
		return false;
	}

	tblname = GetMataTableName(jobData[KEY_SP_SVC_TRAN_ID].c_str());

	ostringstream uri;
	uri << "/" << jobData[KEY_SP_SVC_TRAN_ID] << "/";
	jobData[KEY_URI] = uri.str();

	const char *paramValues[1];
	ostringstream sql;

	sql << "SELECT count(uri) FROM ( ";
	sql << "SELECT uri FROM " << tblname << " WHERE uri LIKE $1 || '%' ";
	sql << "AND deleted_yn = 'N' ";
	if (limit > 0)
		sql << "LIMIT " << limit;
	sql << " ) t";

	paramValues[0] = jobData[KEY_URI].c_str();		

	if (DoSQL(sql.str(), 1, paramValues))
	{
		r = true;
		if (m_pDB->GetNoTuples() > 0)
		{
			total = convert(m_pDB->GetValue(0, 0));
			LOG(LINF, "File total rows (%s : %ju(%ju)).", paramValues[0], total, limit);
		}
		else
		{
			total = 0;
			LOG(LINF, "File total rows(%s : 0).", paramValues[0]);
		}
		m_pDB->PgClear();
	}
	else
		r = false;

	return r;
}

bool CRCDBControl::GetServiceInfoAll(CJobDataMap & jobData)
{
	bool r = true;

	if (jobData[KEY_SP_USER_SEQ].empty())
	{
		LOG(LERR, "User Information empty.(Get Service Info all)");
		return false;
	}

	if (jobData[KEY_SP_SVC_TRAN_ID].size() <= 0)
	{
		LOG(LERR, "There is no information about the service requested(Get Service Info all - tran_id).");
		return false;
	}

	string tblname = GetMataTableName(jobData[KEY_SP_SVC_TRAN_ID].c_str());

	ostringstream sql;

	sql << "SELECT ";
	sql << "u.sp_user_id,u.sp_user_seq, u.sp_user_password,";
	sql << "s.sp_svc_id, s.sp_svc_tran_id,s.max_str_size,s.sp_svc_begin_date,s.sp_svc_end_date,";
	sql << "s.initial_vector,s.private_key,";
	sql << "s.replication_count,s.uri_ignore_case,s.cal_used_depth,s.del_file_keep_time,";
	sql << "s.validate_sp_session_id_yn,";
	sql << "v.mode,";
	sql << "v.auth_server,v.auth_path,v.auth_port,v.auth_timeout,";
	sql << "v.bill_server,v.bill_path,v.bill_port,v.bill_timeout,";
	sql << "s.bandwidth_ctrl_yn,";
	sql << "b.volume_bandwidth_limit,";
	sql << "r.host_name ";

	sql << "FROM t_sms_sp_svc_product s ";
	sql << "LEFT JOIN t_sms_sp_user u ON u.sp_user_seq = s.sp_user_seq ";
	sql << "LEFT JOIN t_sms_sp_svc_product_val v ON v.sp_svc_tran_id = s.sp_svc_tran_id ";
	sql << "LEFT JOIN t_sms_sp_svc_product_band b ON b.sp_svc_tran_id = s.sp_svc_tran_id ";
	sql << "LEFT JOIN " << tblname << " r ON r.sp_svc_tran_id = s.sp_svc_tran_id ";

	sql << "WHERE ";
	sql << "r.depth = 0 ";
	sql << "AND s.sp_user_seq = $1 AND s.sp_svc_tran_id = $2";

	const char *paramValues[2];

	paramValues[0] = jobData[KEY_SP_USER_SEQ].c_str();
	paramValues[1] = jobData[KEY_SP_SVC_TRAN_ID].c_str();

	if (DoSQL(sql.str(), 2, paramValues))
	{
		r = true;
		if (m_pDB->GetNoTuples() == 1)
		{

			const char *_f[] =
			{
				// sql << "u.sp_user_id,u.sp_user_seq, u.sp_user_password,";
				KEY_SP_USER_ID, KEY_SP_USER_SEQ, KEY_SP_USER_PASSWORD,
				// sql << "s.sp_svc_id, s.sp_svc_tran_id,s.max_str_size,s.sp_svc_begin_date,s.sp_svc_end_date,";
				KEY_SP_SVC_ID, KEY_SP_SVC_TRAN_ID,
				KEY_MAX_STR_SIZE, KEY_SP_SVC_BEGIN_DATE, KEY_SP_SVC_END_DATE,
				// sql << "s.initial_vector,s.private_key,";
				KEY_INITIAL_VECTOR, KEY_PRIVATE_KEY,
				// sql << "s.replication_count,s.uri_ignore_case,s.cal_used_depth,s.del_file_keep_time,";
				KEY_REPLICATION_COUNT, KEY_URI_IGNORE_CASE, KEY_CAL_USED_DEPTH, KEY_DEL_FILE_KEEP_TIME,
				// sql << "s.validate_sp_session_id_yn,";
				KEY_VALIDATE_SP_SESSION_ID_YN,
				// sql << "v.mode,";
				KEY_REQ_AUTH_MODE,
				// sql << "v.auth_server,v.auth_path,v.auth_port,v.auth_timeout,";
				KEY_AUTH_SERVER, KEY_AUTH_PATH, KEY_AUTH_PORT, KEY_AUTH_TIMEOUT,
				// sql << "v.bill_server,v.bill_path,v.bill_port,v.bill_timeout,";
				KEY_BILL_SERVER, KEY_BILL_PATH, KEY_BILL_PORT, KEY_BILL_TIMEOUT,
				// sql << "s.bandwidth_ctrl_yn,";
				KEY_BANDWIDTH_CTRL_YN,
				// sql << "b.volume_bandwidth_limit,";
				KEY_VOLUME_BANDWIDTH_LIMIT,
				// sql << "r.host_name ";
				KEY_HOST_NAME,
				0
			};

			for (unsigned int i = 0; _f[i] != NULL ; ++i)
			{
				LOG(LDEV2, "##### [%s] => %s", _f[i], m_pDB->GetValue(0, i));
				jobData[_f[i]] = m_pDB->GetValue(0, i);
			}
		}
		else if (m_pDB->GetNoTuples() == 0)
		{
			LOG(LNOT, "Service information empty.[%s@%s]", 
				jobData[KEY_SP_SVC_TRAN_ID].c_str(),
				jobData[KEY_SP_USER_SEQ].c_str());
		}
		else
		{
			LOG(LNOT, "Service information duplication occurred.[%s@%s]", 
				jobData[KEY_SP_SVC_TRAN_ID].c_str(),
				jobData[KEY_SP_USER_SEQ].c_str());
		}
	}
	else
		r = false;

	m_pDB->PgClear();

	return r;
}

bool CRCDBControl::SetMetaIgnoreCase(CJobDataMap & jobData, bool IgnoreCase)
{
	bool r = true;

	// 기존 형상(8.4) 경우 대소문자 관련 기능은 인덱스로 지원하고 있으므로 
	// 메타 테이블 변경 필요 업으므로 무조건 성공을 리턴함
	if (m_usedisplay == false)
	{ 
		LOG(LNOT, "uri ignorecase Supports INDEX.[%s]", jobData[KEY_SP_SVC_TRAN_ID].c_str());
		return true;
	}		

	string tblname;
	if (jobData[KEY_SP_SVC_TRAN_ID].size() <= 0)
	{
		LOG(LERR, "There is no information about the service requested(Set Meta IgnoreCase - tran_id).");
		return false;
	}

	tblname = GetMataTableName(jobData[KEY_SP_SVC_TRAN_ID].c_str());

	ostringstream sql;

	uint64_t nowtime = GetTimeStamp();

	sql << "UPDATE " << tblname << " SET "
		<< "get_lastmodified = " << nowtime;
	
	if (IgnoreCase)
		sql << ", uri = lower(display_name) ";
	else 
		sql << ", uri = display_name ";

	if (DoSetSQL(sql.str()))
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed service meta ignore case update.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return r;
}

bool CRCDBControl::GetTargetFHS(string & targethost)
{
	ostringstream sql;

	sql << "SELECT fhs_hostname FROM t_fhs_top_status ";
	sql << "WHERE lastupdate >= (NOW() - interval'01 minute') ";

	if (DoSQL(sql.str()))
	{
		
		vector<string> vechosts;
		for (int i = 0; i < m_pDB->GetNoTuples(); i++)
		{
			vechosts.push_back(m_pDB->GetValue(i, 0));
		}

		targethost = vechosts[rand() % vechosts.size()];

		m_pDB->PgClear();
		return true;
	}

	return false;
}

bool CRCDBControl::MakeDir(CJobDataMap & jobData, string & spath, bool & IgnoreCase)
{
	if (jobData[KEY_HOST_NAME].empty())
		GetTargetFHS(jobData[KEY_HOST_NAME]);

	if (jobData[KEY_HOST_NAME].empty())
	{ 
		LOG(LERR, "Target Host Empty.[uri:%s]", spath.c_str());
		return false;
	}

	int depth = count(spath.begin(), spath.end(), '/') - 1;
	_LOG(LDBG, "Make Dir Target Host : %s - %d", jobData[KEY_HOST_NAME].c_str(), depth);

	string tblname = GetMataTableName(jobData[KEY_SP_SVC_TRAN_ID].c_str());

	uint64_t nowtime = GetTimeStamp();

	ostringstream sql;

	sql << "INSERT INTO " << tblname;
	sql << "(";

	sql << "creation_date,get_lastmodified,file_lastmodified";
	sql << ",filename_org,filename_hash,resource_type";
	sql << ",get_content_length,get_content_type";
	sql << ",source";

	sql << ",sp_user_seq,sp_svc_tran_id";
	sql << ",host_name";
	sql << ",depth";
	sql << ",uri,display_name";

	sql << ")";
	sql << " VALUES ";
	sql << "(";
	
	sql << nowtime << "," << nowtime << "," << nowtime;
	sql << ",'','',1";
	sql << ",0,'httpd/unix-directory'";
	sql << ",0";

	sql << ",$1,$2";
	sql << ",$3";
	sql << ",$4";
	if (IgnoreCase)
		sql << ",lower($5),$6";
	else
		sql << ",$5,$6";

	sql << ")";

	ostringstream tmp;
	tmp << depth;
	string sdepth = tmp.str(); tmp.str("");

	const char *paramValues[6];
	
	paramValues[0] = jobData[KEY_SP_USER_SEQ].c_str();
	paramValues[1] = jobData[KEY_SP_SVC_TRAN_ID].c_str();
	paramValues[2] = jobData[KEY_HOST_NAME].c_str();
	paramValues[3] = sdepth.c_str();
	paramValues[4] = spath.c_str();
	paramValues[5] = spath.c_str();


	if (DoSetSQL(sql.str(), 6, paramValues))
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed to create directory.[J:%s]",spath.c_str());
		return false;
	}
	
	return false;
}

// 메타 테이블 삭제
bool CRCDBControl::DropMetaTable(CJobDataMap & jobData)
{
	// 이전 형상(8.3 + PGPOOL) 인 경우 단일 메타 테이블이므로 삭제 할 필요 없음
	if (m_tabletype == 0)
	{
		LOG(LNOT, "Does not delete the meta table.Because it has only one meta table.[%s]"
			, jobData[KEY_SP_SVC_TRAN_ID].c_str());
		return true;
	}

	string tblname;
	if (jobData[KEY_SP_SVC_TRAN_ID].size() <= 0)
	{
		LOG(LERR, "There is no information about the service requested(DROP table - tran_id).");
		return false;
	}

	tblname = GetMataTableName(jobData[KEY_SP_SVC_TRAN_ID].c_str());

	ostringstream sql;

	sql << "DROP TABLE " << tblname;

	if (DoSetSQL(sql.str()))
	{
		return true;
	}
	else
	{
		LOG(LERR, "Failed DROP TABLE meta.[J:%s,J:%s]",
			jobData[KEY_SP_SVC_TRAN_ID].c_str(), jobData[KEY_SP_SVC_ID].c_str());
		return false;
	}

	return true;
}
