#include "CacheOrder.h" #include #include #include "Database.h" #include "Logger.h" // ó¸® loop °£ÀÇ sleep time Á¤ÀÇ #define DEFAULT_SLEEP_TIME 3 // RCDB Á¢¼Ó ½ÇÆÐ ¶Ç´Â Query ½ÇÆÐ µîÀÇ »óȲ ¹ß»ý½Ã #define MAX_SLEEP_TIME 30 // Query ¹®Àå ÀúÀåÀ» À§ÇÑ Buffer Å©±â #define DEFAULT_QUERY_BUFFER_SIZE 2048 // »ý¼ºÀÚ // param [IN] pQueueCacheRequest Cache ¿äû Á¤º¸ ÀúÀå Queue ¿¡ ´ëÇÑ Æ÷ÀÎÅÍ // param [IN] pListCacheJob Cache »ý¼º °ü·Ã Job List °´Ã¼¿¡ ´ëÇÑ Æ÷ÀÎÅÍ // param [IN] pProperFhs Proper FHS Á¤º¸¸¦ ÀúÀåÇÏ´Â °´Ã¼¿¡ ´ëÇÑ Æ÷ÀÎÅÍ CCacheOrder::CCacheOrder( CDataQueue* pQueueCacheRequest, CCacheJobList* pCacheJob, CProperFhs * pProperFhs ) : m_pQueueCacheRequest( pQueueCacheRequest ) , m_pCacheJob( pCacheJob ) , m_pProperFhs( pProperFhs ) { m_threadHandle = 0; m_uSleep = DEFAULT_SLEEP_TIME; // NEW 2014-07-07 ½Å±Ô ¸â¹ö º¯¼ö ÃʱâÈ­ ÄÚµå Ãß°¡. // Init() ¿¡¼­ RCDB Á¢¼Ó ½ÇÆÐ°¡ ¹ß»ý °¡´ÉÇϹǷÎ.. ±¸Çü RCDB Çü»óÀ» »ç¿ëÅä·Ï ¼³Á¤. m_bServiceTableSeparate = false; } // ¼Ò¸êÀÚ CCacheOrder::~CCacheOrder() { // Thread µ¿ÀÛ Á¤Áö ó¸® // - ¸¸¾à Thread °¡ ÀÌ¹Ì Á¾·áµÈ °æ¿ì m_threadHandle ÀÌ ´Ù¸¥ Thread Handle ÀÏ ¼ö ÀÖÀ¸¹Ç·Î // ¾÷¹« Flow ¼öÁ¤½Ã ÁÖÀÇÇÒ °Í if( m_threadHandle != 0 ) pthread_cancel( m_threadHandle ); } // °´Ã¼ ÃʱâÈ­ ¼öÇà bool CCacheOrder::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, "CCacheOrder: t_dav_resource table exist.[Old RCDB Type]" ); } else { // t_dav_resource Å×À̺íÀÌ Á¸ÀçÇÏÁö ¾Ê´Â ¼­ºñ½ºº° Å×ÀÌºí ºÐ¸® Çü»óÀÎ °æ¿ì. m_bServiceTableSeparate = true; _LOG( LINF, "CCacheOrder: t_dav_resource table not exist.[New RCDB Type]" ); } } // RCDB Á¶È¸ °á°ú set ¸¦ clear ó¸® ÈÄ RCDB Á¢¼Ó ÇØÁ¦. rcdb.PgClear(); rcdb.PgCloseDB(); return true; } } // thread¸¦ »ý¼ºÇÏ¿© ¾÷¹« flow ¸¦ ½ÃÀÛ. bool CCacheOrder::Start() { int nRet = ::pthread_create( &m_threadHandle, 0, CCacheOrder::threadFunc, this ); if( nRet != 0 ) { // Thread »ý¼º ½ÇÆÐ½Ã int errorNum = errno; LOG( LERR, "Thread create failed.[%d][%s]", errorNum, strerror( errorNum ) ); return false; } return true; } // ½º·¹µå ÇÔ¼ö void* CCacheOrder::threadFunc( void* arg ) { CCacheOrder* pObject = reinterpret_cast( arg ); pthread_detach( pthread_self() ); while( 1 ) { pthread_testcancel(); pObject->Execute(); pthread_testcancel(); // 1ȸ ¼öÇà ÈÄ ÁöÁ¤µÈ ½Ã°£ ¸¸Å­ ´ë±â sleep( pObject->m_uSleep ); } // NEW 2014-07-07 huibong // Thread Á¾·á½Ã m_threadHandle °ªÀ» ÃʱâÈ­ ó¸®. // - ¼Ò¸êÀÚ¿¡¼­ À߸øµÈ Thread ¸¦ Á¾·áÇÒ ¼ö Àֱ⠶§¹®. pObject->m_threadHandle = 0; return NULL; } // ½º·¹µå ³»¿¡¼­ °¢ loop ´ÜÀ§ ó¸® È£Ãâ ÇÔ¼ö. void CCacheOrder::Execute() { // Request Cache Queue »ó¿¡ ó¸®ÇÒ Data °¡ Á¸ÀçÇÏ´Â °æ¿ì. if( m_pQueueCacheRequest->GetSize() > 0 ) { bool bResult = PushRequestToJob(); // ó¸® °á°ú¿¡ µû¶ó loop sleep time Á¶Á¤ if( bResult == true ) m_uSleep = DEFAULT_SLEEP_TIME; else { // RCDB ¿¬°á ½ÇÆÐ, Queury ¼öÇà ½ÇÆÐ µîÀÇ ¿À·ù ¹ß»ý½Ã m_uSleep = MAX_SLEEP_TIME; } } else { // ó¸®ÇÒ Data °¡ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì. m_uSleep = DEFAULT_SLEEP_TIME; } } // Cache Requet Queue ¿¡ ÀúÀåµÈ ¿äûÀ» °Ë»çÇÏ¿©.... // cache »ý¼º Job ¿¡ Ãß°¡ÇÏ´Â ±â´ÉÀ» ¼öÇà bool CCacheOrder::PushRequestToJob() { // RCDB ¿¬°á °ü·Ã °´Ã¼. // - RCDB ¿¬°áÀº Job ¿¡ µî·Ï°¡´ÉÇÑ Data °¡ Á¸ÀçÇÒ °æ¿ì¿¡¸¸ ¼öÇàµÇµµ·Ï ÇÑ´Ù. DataBase rcdb; bool bDbConnected = false; // RCDB ¿¬°á »óÅ Á¤º¸ ÀúÀå º¯¼ö // Queue ¿¡¼­ Data ¸¦ Pop ÇÑ ÈÄ // ÇØ´ç Á¤º¸°¡ CacheJobList ¿¡ ÀÌ¹Ì µî·ÏµÈ Á¤º¸ÀÎÁö È®ÀÎ // ¹Ìµî·Ï Á¤º¸ÀÎ °æ¿ì RCDB Á¶È¸¸¦ ¼öÇàÇÏ¿© // - Cache ¸¦ ¼öÇàÇÒ FHS Á¤º¸¸¦ ¼±ÅÃÇÑ ÈÄ // - ÇØ´ç Content Á¤º¸¸¦ Cache Job ¿¡ µî·Ï ó¸®ÇÑ´Ù. // queue ¿¡¼­ ²¨³½ Á¤º¸¸¦ ÀúÀåÇϱâ À§ÇÑ º¯¼ö CCacheRequestData requestData; // Query ¹®Àå ÀúÀåÀ» À§ÇÑ ¹öÆÛ »ý¼º char szQuery[DEFAULT_QUERY_BUFFER_SIZE]; // Query ¼öÇà °á°ú°ª ÀúÀåÀ» À§ÇÑ º¯¼ö.. int nResult = 0; while( m_pQueueCacheRequest->GetSize() > 0 ) { // queue ¿¡ ÀúÀåµÈ ù¹øÂ° data º¹»ç (queue ¿¡¼­ »èÁ¦µÈ »óÅ ¾Æ´Ô) requestData = m_pQueueCacheRequest->Front(); // ÇØ´ç Á¤º¸¸¦ Job List ¿¡ ÀúÀå °¡´ÉÇÑÁö È®ÀÎ if( m_pCacheJob->IsExist( requestData ) == true ) { // ÀÌ¹Ì µ¿ÀÏ Á¤º¸°¡ Job List ¿¡ Á¸ÀçÇÏ´Â °æ¿ì... // queue ¿¡¼­ pop ÇØ¼­ ¹ö¸². _LOG( LINF, "Cache request already exist.[%s]", requestData.m_strFileNameHash.c_str() ); m_pQueueCacheRequest->Pop(); continue; } // RCDB ¿¡¼­ ÇØ´ç content ¿¡ ´ëÇÑ Á¤º¸ Á¶È¸ // DB ¿¬°áÀÌ µÇÁö ¾ÊÀº »óÅÂÀÎ °æ¿ì. // - Queue Ç׸ñ Áß Job ¿¡ µî·ÏÇØ¾ß ÇÏ´Â Ç׸ñÀÌ Á¸ÀçÇÒ °æ¿ì¿¡¸¸ RCDB ¿¬°á ¸ñÀû if( bDbConnected == false ) { // 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 Á¢¼ÓÀÌ ¾ÈµÉ¶§... // - ÇöÀç Queue ¿¡ ÀúÀåµÈ Cache Request ¿äûÀ» ¸ðµÎ ¹ö¸®°í // - false ¹ÝȯÇÏ¿© ƯÁ¤½Ã°£ µ¿¾È sleep µÇµµ·Ï ó¸®. LOG( LERR, "RCDB connection failed. Cache request all trhow [%u]" , m_pQueueCacheRequest->GetSize() ); // Queue ¿äû ¸ðµÎ »èÁ¦ ó¸® m_pQueueCacheRequest->Init(); return false; } else { bDbConnected = true; } } // Query Á¶¸³ // - Àü´Þ¹ÞÀº filename_hash , content_length, FHS Á¤º¸¸¦ ÀÌ¿ëÇÏ¿© // - ÇØ´ç ¹°¸® ÆÄÀϰú ¿¬°áµÈ uri ÃßÃâ ( uri ¸¦ Á÷Á¢ ¼ö½ÅÇÒ °æ¿ì..´ë¼Ò¹®ÀÚ ¹«½Ã ±â´É ¶§¹®¿¡ Á¶È¸ ºÒ°¡) // - ÃßÃâµÈ uri ¿Í ¿¬°áµÈ Àåºñ Á¤º¸¸¦ Á¶È¸ÇÑ´Ù. // - ORDER BY Á¶°Ç¿¡ ÀÇÇØ is_cache °ªÀÌ N-R-Y ¼øÀ¸·Î ³ªÅ¸³². // - COPY µîÀ¸·Î ÀÎÇØ Query °á°ú¿¡´Â Áߺ¹µÈ host_name ÀÌ Á¸Àç °¡´ÉÇÔ. // t_dav_resource Å×ÀÌºí »ç¿ë RCDB ÀÎ °æ¿ì if( m_bServiceTableSeparate == false ) { sprintf( szQuery, "SELECT host_name, filename_hash, is_cache " "FROM t_dav_resource " "WHERE uri IN " " ( SELECT uri FROM t_dav_resource " " WHERE filename_hash = '%s' " " AND host_name = '%s' " " AND get_content_length = %llu " " AND deleted_yn = 'N' " " ) " " AND get_content_length = %llu " " AND deleted_yn = 'N' " "ORDER BY is_cache ASC; " , requestData.m_strFileNameHash.c_str() , requestData.m_strRequestHost.c_str() , requestData.m_uContentLength , requestData.m_uContentLength ); } else { // ½ÅÇü RCDB Çü»óÀÎ °æ¿ì. sprintf( szQuery, "SELECT host_name, filename_hash, is_cache " "FROM t_meta_%s " "WHERE uri IN " " ( SELECT uri FROM t_meta_%s " " WHERE filename_hash = '%s' " " AND host_name = '%s' " " AND get_content_length = %llu " " AND deleted_yn = 'N' " " ) " " AND get_content_length = %llu " " AND deleted_yn = 'N' " "ORDER BY is_cache ASC; " , requestData.m_strServiceSeq.c_str() , requestData.m_strServiceSeq.c_str() , requestData.m_strFileNameHash.c_str() , requestData.m_strRequestHost.c_str() , requestData.m_uContentLength , requestData.m_uContentLength ); } // Query ½ÇÇà ¹× °á°ú È®ÀÎ rcdb.PgDoExec( szQuery ); nResult = rcdb.PgResult( DataBase::NOT_CLEAR ); if( nResult < 0 ) { // RCDB t_dav_resource Å×À̺í Á¶È¸ ½ÇÆÐ½Ã // - RCDB ¿¬°á ½ÇÆÐ ¶Ç´Â Query ½ÇÆÐ·Î ÀÎÇÑ ¹®Á¦ ¹ß»ý °¡´É. // - µû¶ó¼­ RCDB ¿¬°á ÇØÁ¦ ó¸®, Queue Pop ó¸®ÇÑ ÈÄ // - ·çÇÁ¸¦ °è¼Ó ¼öÇàó¸® LOG( LERR, "RCDB t_dav_resource cache select failed.[%s][%s]" , rcdb.GetErrorMessage().c_str(), szQuery ); rcdb.PgClear(); rcdb.PgCloseDB(); bDbConnected = false; m_pQueueCacheRequest->Pop(); continue; } // °á°ú Row ¼ö È®ÀÎ. nResult = rcdb.GetNoTuples(); if( nResult <= 0 ) { // ÇØ´ç Content °¡ Á¸ÀçÇÏÁö ¾Ê°Å³ª... ¿À·ù ¹ß»ý½Ã. // - ±×³É ¹ö¸°´Ù. // - ÀÌ·Î ÀÎÇØ FHS ¿¡ meta ±âÁØÀ¸·Î »èÁ¦ ºÒ°¡´ÉÇÑ ÆÄÀÏÀÌ ³²°Ô µÈ´Ù. _LOG( LINF, "cache request content not found in RCDB.[%d] [%s][%s][%llu]" , nResult , requestData.m_strRequestHost.c_str() , requestData.m_strFileNameHash.c_str() , requestData.m_uContentLength ); } else { // °á°ú Row ¼ö°¡ Á¸ÀçÇÏ´Â °æ¿ì... CCacheData cacheData; cacheData.m_requestData = requestData; // °á°ú Á¤º¸ Áß.. Request ¿äûÀ» º¸³½ Àåºñ°¡ ¾Æ´Ñ FHS À» Cache »ý¼º ¿øº»À¸·Î ¼±Åà // - order by Á¶°Ç¿¡ ÀÇÇØ is_cache °¡ N-R-Y ¼øÀ¸·Î Àåºñ Á¤º¸°¡ ³ªÅ¸³ª¹Ç·Î... // - ¿øº», º¹Á¦º», cache º» ¼øÀ¸·Î »ç¿ëµÉ ¼ø¼­°¡ Á¤ÇØÁü. for( int i = 0; i < nResult; ++i ) { // host name ÀÌ °°Áö ¾ÊÀº °æ¿ì. if( strcasecmp( rcdb.GetValue( i, 0 ), requestData.m_strRequestHost.c_str() ) != 0 ) { cacheData.m_strSourceHost = rcdb.GetValue( i, 0 ); cacheData.m_strSourceFilenameHash = rcdb.GetValue( i, 1 ); // source ·Î »ç¿ëÇÒ Ã¹¹øÂ° Àåºñ¸¦ ãÀº °æ¿ì... // - ´õ ÀÌ»ó ·çÇÁ´Â Àǹ̰¡ ¾øÀ¸¹Ç·Î.. break; } } // ¸¸¾à ¿øº» 1°³¸¸ Á¸ÀçÇÏ´Â °æ¿ì... // - ±×³É ¿äû Á¤º¸¸¦ ±×´ë·Î »ç¿ë. if( cacheData.m_strSourceHost.empty() == true ) { cacheData.m_strSourceHost = requestData.m_strRequestHost; cacheData.m_strSourceFilenameHash = requestData.m_strFileNameHash; } // ignore FHS list ±¸¼º // - ºü¸¥ 󸮸¦ À§ÇØ Á¶È¸ °á°ú 󸮽à Áߺ¹ host_name Á¤º¸¸¦ Á¦°ÅÇÑ´Ù. std::list ignoreFhsList; std::string strTemp; for( int j = 0; j < nResult; ++j ) { strTemp = rcdb.GetValue( j, 0 ); ignoreFhsList.push_back( strTemp ); } // Áߺ¹ Á¦°Å ( sort() ÈÄ unique() ÇÔ¼ö È£ÃâÇØ¾ß Áߺ¹ Á¦°Å °¡´É ) ignoreFhsList.sort(); ignoreFhsList.unique(); // Target FHS ¼±Á¤ ó¸® std::vector vecProperFhs; if( m_pProperFhs->GetProperFhs( 1, vecProperFhs, ignoreFhsList ) == false ) { // Proper FHS ¼±Åà ½ÇÆÐ½Ã... // ÇØ´ç ¿äûÀ» ±×³É ¹ö¸°´Ù... _LOG( LWAR, "cache request not found proper fhs. throw.[%s][%s][%llu]" , requestData.m_strRequestHost.c_str() , requestData.m_strFileNameHash.c_str() , requestData.m_uContentLength ); } else { // Proper FHS ¼±Åà ¼º°ø½Ã.. // - ÇØ´ç Á¤º¸¸¦ CacheData ¿¡ ÀÔ·ÂÇÑ ÈÄ... // - Job À¸·Î µî·Ï ó¸® cacheData.m_strTargetHost = vecProperFhs.front(); m_pCacheJob->Register( cacheData ); } } // Queue Pop ó¸® ÈÄ // ´ÙÀ½ Query »ç¿ëÀ» ´ëºñÇÏ¿© °á°ú set clear ó¸®. m_pQueueCacheRequest->Pop(); rcdb.PgClear(); } // RCDB ¿¬°áÀÌ µÇ¾î ÀÖ´Â °æ¿ì.. Á¾·á ó¸® if( bDbConnected == true ) { rcdb.PgClear(); rcdb.PgCloseDB(); } return true; }