#include "CacheDelete.h" #include #include #include "Logger.h" #include "Database.h" #include "Util.h" #include "ServiceConfig.h" // Query ¹®Àå ÀúÀåÀ» À§ÇÑ Buffer Å©±â #define DEFAULT_QUERY_BUFFER_SIZE 512 // sec ¸¦ micro-sec ·Î ´ÜÀ§ º¯È¯½Ã ȯ»ê °è¼ö. #define SEC_TO_MICROSEC (1000000LL) // »èÁ¦ ÀÛ¾÷½Ã ½ÃÀÛ ½Ã°£À» ¼³Á¤Çϱâ À§ÇÑ º¸Á¤°ª. #define CACHE_DELETE_RANGE (60*60*48) // 48½Ã°£ // »èÁ¦ ÁÖ±â ( sec ´ÜÀ§) #define CAHCE_DEL_CHECK_TERM_SEC (20 * 60) // 20ºÐ // »ý¼ºÀÚ CCacheDelete::CCacheDelete() { m_threadHandle = 0; // NEW 2014-06-16 ½Å±Ô ¸â¹ö º¯¼ö ÃʱâÈ­ ÄÚµå Ãß°¡. // Init() ¿¡¼­ RCDB Á¢¼Ó ½ÇÆÐ°¡ ¹ß»ý °¡´ÉÇϹǷÎ.. ±¸Çü RCDB Çü»óÀ» »ç¿ëÅä·Ï ¼³Á¤. m_bServiceTableSeparate = false; } // ¼Ò¸êÀÚ CCacheDelete::~CCacheDelete() { // Thread µ¿ÀÛ Á¤Áö ó¸® // - ¸¸¾à Thread °¡ ÀÌ¹Ì Á¾·áµÈ °æ¿ì m_threadHandle ÀÌ ´Ù¸¥ Thread Handle ÀÏ ¼ö ÀÖÀ¸¹Ç·Î // ¾÷¹« Flow ¼öÁ¤½Ã ÁÖÀÇÇÒ °Í if( m_threadHandle != 0 ) pthread_cancel( m_threadHandle ); } // °´Ã¼ ÃʱâÈ­ ¼öÇà bool CCacheDelete::Init() { // RCDB Á¢¼Ó Á¤º¸ Load. m_rcdbInfo.Load(); // RCDB Á¢¼Ó 󸮸¦ À§ÇÑ °´Ã¼ »ý¼º DataBase rcdb; // RCDB Á¢¼Ó ½Ãµµ ¹× Á¢¼Ó ½ÇÆÐ½Ã if( rcdb.PgOpenDB( m_rcdbInfo.m_strRcdbIp, m_rcdbInfo.m_nRcdbPort , m_rcdbInfo.m_strRcdbName, m_rcdbInfo.m_strRcdbAcct , m_rcdbInfo.m_strRcdbAcctPw ) == NULL ) { LOG( LERR, "RCDB connection failed." ); return false; } else { // Á¢¼Ó ¼º°øÇÑ °æ¿ì... LOG( LINF, "RCDB connection test ok..." ); // NEW 2014-06-23 huibong // ¼­ºñ½º table ºÐ¸®µÈ ½Å±Ô Çü»óÀÎÁö.. ±¸Çü Çü»óÀÎÁö üũÇÏ¿© // m_bServiceTableSeparate º¯¼ö ¼³Á¤ ó¸®. // ÇØ´ç º¯¼ö ÃʱâÈ­´Â »ý¼ºÀÚ¿¡¼­ 1Â÷·Î ¼öÇàÇÔ. char szQuery[1024]; snprintf( szQuery, 1023, "SELECT * FROM pg_tables WHERE schemaname = 'public' AND tablename = 't_dav_resource' " ); rcdb.PgDoExec( szQuery ); if( rcdb.PgResult( DataBase::NOT_CLEAR ) < 0 ) { // Query ¼öÇà °á°ú ¿À·ù ¹ß»ý½Ã... // - pg_tables °¡ Á¸ÀçÇÏÁö ¾ÊÀ» °æ¿ì ¿À·ù ¹ß»ý °¡´É... // - ÀÌ´Â RCDB °¡ ¾ÆÁ÷ ÀûÀýÇÏ°Ô ±¸¼ºµÇÁö ¾Ê¾Ò´Ù´Â ÀǹÌÀ̹ǷÎ... Init()ÇÔ¼ö¸¦ ¿À·ù·Î ó¸®ÇÑ´Ù. LOG( LERR, "RCDB t_dav_resource exist check failed.[%s][%s]", rcdb.GetErrorMessage().c_str(), szQuery ); rcdb.PgClear(); rcdb.PgCloseDB(); return false; } else { // Query ¼öÇàÀÌ Á¤»óÀÎ °æ¿ì. int nResult = rcdb.GetNoTuples(); if( nResult > 0 ) { // t_dav_resource Å×À̺íÀÌ Á¸ÀçÇÏ´Â °æ¿ì... m_bServiceTableSeparate = false; _LOG( LINF, "CCacheDelete: t_dav_resource table exist.[Old RCDB Type]" ); } else { // t_dav_resource Å×À̺íÀÌ Á¸ÀçÇÏÁö ¾Ê´Â ¼­ºñ½ºº° Å×ÀÌºí ºÐ¸® Çü»óÀÎ °æ¿ì. m_bServiceTableSeparate = true; _LOG( LINF, "CCacheDelete: t_dav_resource table not exist.[New RCDB Type]" ); } } // RCDB Á¶È¸ °á°ú set ¸¦ clear ó¸® ÈÄ RCDB Á¢¼Ó ÇØÁ¦. rcdb.PgClear(); rcdb.PgCloseDB(); return true; } } // thread¸¦ »ý¼ºÇÏ¿© ¾÷¹« flow ¸¦ ½ÃÀÛ. bool CCacheDelete::Start() { int nRet = ::pthread_create( &m_threadHandle, NULL, CCacheDelete::threadFunc, this ); if( nRet != 0 ) { // Thread »ý¼º ½ÇÆÐ½Ã int errorNum = errno; LOG( LERR, "Thread create failed.[%d][%s]", errorNum, strerror( errorNum ) ); return false; } return true; } void * CCacheDelete::threadFunc( void * arg ) { CCacheDelete* pObject = reinterpret_cast( arg ); pthread_detach( pthread_self() ); while( 1 ) { pthread_testcancel(); pObject->Execute(); pthread_testcancel(); sleep( CAHCE_DEL_CHECK_TERM_SEC ); } // NEW 2014-06-23 huibong // Thread Á¾·á½Ã m_threadHandle °ªÀ» ÃʱâÈ­ ó¸®. // - ¼Ò¸êÀÚ¿¡¼­ À߸øµÈ Thread ¸¦ Á¾·áÇÒ ¼ö Àֱ⠶§¹®. pObject->m_threadHandle = 0; // CHG 2014-06-23 huibong // detach µÈ Thread ¿¡ ´ëÇØ pthread_exit() È£Ãâ½Ã // ±âÁØ ÇÒ´ç ÀÚ¿ø¿¡ ´ëÇÑ ÇØÁö 󸮰¡ µÇÁö ¾Ê¾Æ ¸Þ¸ð¸® ´©¼ö ¹ß»ý °¡´É( FreeBSD ftsd ¹ß»ý) // µû¶ó¼­ À̸¦ ÇØ°áÇϱâ detach µÈ thread ¿¡ ´ëÇØ pthread_exit() È£Ãâ ÄÚµå Á¦°Å. //pthread_exit(NULL); return NULL; } // ½º·¹µå ³»¿¡¼­ °¢ loop ´ÜÀ§ ó¸® È£Ãâ ÇÔ¼ö. void CCacheDelete::Execute() { // ±¸Çü t_dav_resource Å×ÀÌºí »ç¿ë½Ã if( m_bServiceTableSeparate == false ) { DeleteFromOldDB(); } else { // ½ÅÇü RCDB Çü»ó »ç¿ë½Ã DeleteFromDB(); } } // RCDB t_dav_resource Å×ÀÌºí¿¡¼­ À¯È¿±â°£ÀÌ Áö³­ Hot Content Cache Content ¸¦ »èÁ¦ ó¸® // - ±¸Çü RCDB Áö¿ø ¸ñÀû bool CCacheDelete::DeleteFromOldDB() { // 1. ÇöÀç ½Ã°£Á¤º¸¸¦ ±¸ÇÑ´Ù.( micro-second ´ÜÀ§) long long timeNow = longtime_now(); if( timeNow < 0 ) { LOG( LERR, "longtime_now function error [%lld]", timeNow ); return false; } // 2. RCDB ¿Í ¿¬°á ó¸®. DataBase rcdb; if( rcdb.PgOpenDB( m_rcdbInfo.m_strRcdbIp, m_rcdbInfo.m_nRcdbPort , m_rcdbInfo.m_strRcdbName, m_rcdbInfo.m_strRcdbAcct , m_rcdbInfo.m_strRcdbAcctPw ) == NULL ) { // RCDB Á¢¼Ó ½ÇÆÐ½Ã LOG( LERR, "RCDB connection failed." ); return false; } // 3. t_dav_resource Å×ÀÌºí¿¡¼­ À¯È¿±â°£ÀÌ Áö³­ Cache Content ¸¦ »èÁ¦ »óÅ·Πupdate ó¸® // Query ¹®Àå ÀúÀåÀ» À§ÇÑ ¹öÆÛ »ý¼º char szQuery[DEFAULT_QUERY_BUFFER_SIZE]; int nResult = 0; // ó¸® ´ë»ó ½Ã°£ ±¸°£ °è»ê (micro-second ´ÜÀ§ ) long long timeStart; long long timeEnd; // ÇöÀç½Ã°£ ±âÁØÀ¸·Î Hot Content Cache ÀÇ º¸Á¸ ¸¸·á ½Ã°£À» °è»ê. timeEnd = timeNow - ( CServiceConfig::GetInstance()->GetCacheFileTimeout() * SEC_TO_MICROSEC ); // Á¶È¸ ½ÃÀÛ ½Ã°£À» °è»ê. // - º» °ªÀÌ ¾øÀ» °æ¿ì... RCDB¸¦ Full Scan ÇØ¾ß ÇϹǷÎ.. RCDB ¿¡ ºÎÇÏ ¹ß»ý °¡´É. // - µû¶ó¼­ º¸Á¸ ¸¸·á ½Ã°£ ÀÌÀü 48 ½Ã°£ Á¤µµ·Î Á¶È¸ ¹üÀ§¸¦ °¨¼Ò½ÃŲ´Ù. timeStart = timeNow - ( ( CServiceConfig::GetInstance()->GetCacheFileTimeout() + CACHE_DELETE_RANGE ) * SEC_TO_MICROSEC ); snprintf(szQuery, DEFAULT_QUERY_BUFFER_SIZE - 1, "UPDATE t_dav_resource SET deleted_yn = 'Y' ,get_lastmodified = %lld " "WHERE is_cache = 'Y' AND deleted_yn = 'N' " "AND get_lastmodified >= '%lld' " "AND get_lastmodified <= '%lld';" , timeNow, timeStart, timeEnd ); // Query ½ÇÇà rcdb.PgDoExec(szQuery); // Update ó¸® °á°ú Row ¼ö È®ÀÎ. nResult = rcdb.GetCmdTuples(); if( nResult > 0 ) { _LOG( LINF, "CCacheDelete: t_dav_resource delete count[%d]", nResult ); } rcdb.PgClear(); rcdb.PgCloseDB(); return true; } // RCDB t_meta_xxx Å×ÀÌºí¿¡¼­ À¯È¿±â°£ÀÌ Áö³­ Hot Content Cache Content ¸¦ »èÁ¦ ó¸® // - ½ÅÇü RCDB Áö¿ø ¸ñÀû bool CCacheDelete::DeleteFromDB() { // 1. ÇöÀç ½Ã°£Á¤º¸¸¦ ±¸ÇÑ´Ù.( micro-second ´ÜÀ§) long long timeNow = longtime_now(); if( timeNow < 0 ) { LOG( LERR, "longtime_now function error [%lld]", timeNow ); return false; } // 2. RCDB ¿Í ¿¬°á ó¸®. DataBase rcdb; if( rcdb.PgOpenDB( m_rcdbInfo.m_strRcdbIp, m_rcdbInfo.m_nRcdbPort , m_rcdbInfo.m_strRcdbName, m_rcdbInfo.m_strRcdbAcct , m_rcdbInfo.m_strRcdbAcctPw ) == NULL ) { // RCDB Á¢¼Ó ½ÇÆÐ½Ã LOG( LERR, "RCDB connection failed." ); return false; } // Query ¹®Àå ÀúÀåÀ» À§ÇÑ ¹öÆÛ »ý¼º char szQuery[DEFAULT_QUERY_BUFFER_SIZE]; int nResult = 0; // 3. RCDB t_sms_sp_svc_product Å×ÀÌºí¿¡ ÀúÀåµÈ ¼­ºñ½º Á¤º¸¸¦ Á¶È¸ÇÑ´Ù. snprintf( szQuery, DEFAULT_QUERY_BUFFER_SIZE - 1, "SELECT sp_svc_tran_id FROM t_sms_sp_svc_product ORDER BY sp_svc_tran_id DESC " ); // Query ½ÇÇà rcdb.PgDoExec( szQuery ); nResult = rcdb.PgResult( DataBase::NOT_CLEAR ); if( nResult < 0 ) { // Query ¿À·ù ¹ß»ý½Ã // - RCDB ¿¬°á ½ÇÆÐ ¶Ç´Â // - t_sms_sp_svc_product Å×À̺íÀÌ Á¸ÀçÇÏÁö ¾ÊÀ» °æ¿ì. LOG( LERR, "RCDB t_sms_sp_svc_product query error.[%s][%s]" , rcdb.GetErrorMessage().c_str(), szQuery ); rcdb.PgClear(); rcdb.PgCloseDB(); return false; } // Á¶È¸µÈ °¢ °í°´»ç Á¤º¸ È®ÀÎ nResult = rcdb.GetNoTuples(); if( nResult <= 0 ) { // °í°´»ç°¡ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì _LOG( LINF, "CCacheDelete: service not found from t_sms_sp_svc_product.[%d]" , nResult ); rcdb.PgClear(); rcdb.PgCloseDB(); return true; } // Á¶È¸µÈ °í°´»ç Á¤º¸¸¦ º¯¼ö¿¡ ÀúÀå. std::vector vecService; std::string strTemp; for( int i = 0; i < nResult; i++ ) { strTemp = rcdb.GetValue( i, 0 ); if( strTemp.size() > 0 ) vecService.push_back( strTemp ); } rcdb.PgClear(); // º¯¼ö¿¡ ÀúÀåµÈ ¼­ºñ½º Á¤º¸ÀÇ ¼ö¸¦ ÃÖÁ¾ È®ÀÎ if( vecService.empty() == true ) { // À¯È¿ÇÑ ¼­ºñ½º Á¤º¸°¡ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì. _LOG( LINF, "CCacheDelete: service not found from t_sms_sp_svc_product." ); rcdb.PgCloseDB(); return true; } // 4. ·çÇÁ¸¦ µ¹¸é¼­ // °¢ ¼­ºñ½ºº° t_meta_xx Å×ÀÌºí¿¡¼­ À¯È¿±â°£ÀÌ Áö³­ Cache Content ¸¦ »èÁ¦ »óÅ·Πupdate ó¸® // ó¸® ´ë»ó ½Ã°£ ±¸°£ °è»ê (micro-second ´ÜÀ§ ) long long timeStart; long long timeEnd; // ÇöÀç½Ã°£ ±âÁØÀ¸·Î Hot Content Cache ÀÇ º¸Á¸ ¸¸·á ½Ã°£À» °è»ê. timeEnd = timeNow - ( CServiceConfig::GetInstance()->GetCacheFileTimeout() * SEC_TO_MICROSEC ); // Á¶È¸ ½ÃÀÛ ½Ã°£À» °è»ê. // - º» °ªÀÌ ¾øÀ» °æ¿ì... RCDB¸¦ Full Scan ÇØ¾ß ÇϹǷÎ.. RCDB ¿¡ ºÎÇÏ ¹ß»ý °¡´É. // - µû¶ó¼­ º¸Á¸ ¸¸·á ½Ã°£ ÀÌÀü 48 ½Ã°£ Á¤µµ·Î Á¶È¸ ¹üÀ§¸¦ °¨¼Ò½ÃŲ´Ù. timeStart = timeNow - ( ( CServiceConfig::GetInstance()->GetCacheFileTimeout() + CACHE_DELETE_RANGE ) * SEC_TO_MICROSEC ); std::vector< std::string >::const_iterator it; for( it = vecService.begin(); it != vecService.end(); ++it ) { snprintf( szQuery, DEFAULT_QUERY_BUFFER_SIZE - 1, "UPDATE t_meta_%s SET deleted_yn = 'Y' ,get_lastmodified = %lld " "WHERE is_cache = 'Y' AND deleted_yn = 'N' " "AND get_lastmodified >= '%lld' " "AND get_lastmodified <= '%lld';" , it->c_str() , timeNow, timeStart, timeEnd ); // Query ½ÇÇà rcdb.PgDoExec( szQuery ); // Update ó¸® °á°ú Row ¼ö È®ÀÎ. nResult = rcdb.GetCmdTuples(); if( nResult > 0 ) { _LOG( LINF, "CCacheDelete: t_meta_%s delete count[%d]", it->c_str(), nResult ); } rcdb.PgClear(); } // ÀÛ¾÷ÀÌ ¿Ï·áµÈ °æ¿ì... RCDB ¿¬°á ÇØÁ¦. rcdb.PgClear(); rcdb.PgCloseDB(); return true; }