This commit is contained in:
biosvos
2026-08-07 17:38:18 +09:00
commit 873193a243
9613 changed files with 2755992 additions and 0 deletions
+266
View File
@@ -0,0 +1,266 @@
#include "StorageInfo.h"
#include "Logger.h"
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/ucred.h>
#include <sys/mount.h>
#include <math.h>
// 생성자
CStorageInfo::CStorageInfo()
{
// 멤버변수 초기화
m_vecStorageInfo.clear();
}
// 소멸자
CStorageInfo::~CStorageInfo()
{
m_vecStorageInfo.clear();
}
// 전달받은 경로로부터.. 상위 Path 정보를 추출하여 전달한다.
// 오류 발생시 [out] 값인 strUpperPath 가 empty 된다.
void CStorageInfo::GetUpperPath( const std::string & strSourcePath, std::string & strUpperPath )
{
// 인자로 전달되는 strSourcePath 끝에.. '/' 가 이미 제거되었다고 판단하고 작업을 수행한다.
std::string::size_type pos = strSourcePath.rfind( '/' );
if( pos == std::string::npos )
{
// 찾지 못한 경우...
// out 값을 empty 처리시킨다.
LOG( LNOT, "upper path not found. source[%s]", strSourcePath.c_str() );
strUpperPath.clear();
return;
}
// 찾은 경우..
strUpperPath = strSourcePath.substr( 0, pos );
// 추출된 경로가... 최상위 '/' 인 경우.. 유효하지 않으므로 오류로 처리한다.
if( strcmp( strUpperPath.c_str(), "/" ) == 0 )
{
LOG( LNOT, "upper path not vaild that root path. [%s]", strUpperPath.c_str() );
strUpperPath.clear();
}
return;
}
// 초기화 함수
// - szRoot : Content 저장 최상위 경로 정보.
bool CStorageInfo::Init( const char * szRoot )
{
// 전달받은 최상위 경로 정보에 대한 Check
if( szRoot == NULL || strlen( szRoot ) <= 0 )
{
LOG( LERR, "storage root path not valid.");
return false;
}
// 추출된 정보 저장을 위한 임시변수
int iMountCount = 0;
struct statfs * pMountBuf = NULL;
std::vector< struct stStorageInfo > vecStorageAll;
std::vector< struct stStorageInfo >::iterator it;
struct stStorageInfo stStorage;
// 추출 정보 저장 및 멤버 변수 초기화
vecStorageAll.clear();
m_vecStorageInfo.clear();
// Mount 정보 추출
// - MNT_WAIT flag 사용시 정확한 정보를 추출, 하지만 block 발생 가능
// - 따라서 항상 정확한 정보를 추출할 필요는 없으며.. block 이 발생하지 않도록
// - MNT_NOWAIT flag 사용한다.
iMountCount = getmntinfo( &pMountBuf, MNT_NOWAIT );
if( iMountCount == 0 )
{
// 정보 추출 실패시 오류 내역 로깅
int errorNum = errno;
LOG( LERR, "Storage info init error. getmntinfo() fail[%d]. [%d][%s]"
, iMountCount, errorNum, strerror( errorNum ) );
return false;
}
// 추출된 mount 관련 모든 정보를 임시 변수에 저장
for( int i = 0; i < iMountCount; i++ )
{
stStorage.strName = pMountBuf[i].f_mntonname;
stStorage.strFsTypeName = pMountBuf[i].f_fstypename;
stStorage.ulUsedByte = ( pMountBuf[i].f_blocks - pMountBuf[i].f_bfree ) * pMountBuf[i].f_bsize;
stStorage.ulAvailableByte = pMountBuf[i].f_bavail * pMountBuf[i].f_bsize;
stStorage.usage = 0;
vecStorageAll.push_back( stStorage );
}
// 전달받은 mount 최상위 경로와 동일한 명칭의 mount 가 존재하는 검사
// - 이럴 경우는 거의 없는데.. 혹시나 해서 기능 탑재함.
for( it = vecStorageAll.begin(); it < vecStorageAll.end(); it++ )
{
if( strcmp( szRoot, it->strName.c_str() ) == 0 )
{
m_vecStorageInfo.push_back( *it );
}
}
// 전달받은 최상위 mount 정보와 동일한 명칭의 mount 가 존재하지 않는 경우..
// - sub path 부분을 제외한 후 다시 장비 Mount 정보와 비교한다.
// - 장비 mount 정보를 찾을 때까지 본 비교를 반복하여 수행한다.
if( m_vecStorageInfo.empty() == true )
{
std::string strPreviousPath = szRoot;
std::string strCurrentPath = szRoot;
do
{
// 수정된 경로 정보만을 가지고 부분 비교를 수행....
for( it = vecStorageAll.begin(); it < vecStorageAll.end(); it++ )
{
// 부분 비교 처리
if( strncmp( strCurrentPath.c_str(), it->strName.c_str(), strlen( strCurrentPath.c_str() ) ) == 0 )
{
m_vecStorageInfo.push_back( *it );
}
}
// 위에서 정보 추출이 실패한 경우..상위 Path 정보를 추출한다. ( /user2/dav_storage, /stg/node0/aa/bb 등으로 설정된 경우를 위해 )
if( m_vecStorageInfo.empty() == true )
{
GetUpperPath( strPreviousPath, strCurrentPath );
if( strCurrentPath.empty() == true )
{
// 상위 path 가 더이상 유효하지 않은 경우.
break;
}
strPreviousPath = strCurrentPath;
}
} while( m_vecStorageInfo.empty() == true );
}
// 임시 vector 에 저장된 내용 초기화
vecStorageAll.clear();
// 최종
if( m_vecStorageInfo.empty() == true )
{
LOG( LERR, "Storage info init error. root path[%s] not found in system mount.", szRoot );
return false;
}
// 추출 성공시
// - Storage 사용률 정보 계산해서 저장해 놓는다.
for( it = m_vecStorageInfo.begin(); it < m_vecStorageInfo.end(); it++ )
{
if( it->ulAvailableByte + it->ulUsedByte == 0 )
it->usage = 100;
else
{
// 사용률은 정수로 구하며... 나머지가 존재할 경우... 올림 처리한다.
it->usage = ( int ) ceil( ( double ) it->ulUsedByte / ( it->ulUsedByte + it->ulAvailableByte ) * 100.0 );
}
}
return true;
}
// 멤버 vector 에 저장된 경로의 Total Size, Total availsize, Max usage 정보를 반환.
bool CStorageInfo::GetStorageSizeInfo( uint64_t & ulFhsTotal, uint64_t & ulFhsAvailable, int & iMaxUsage )
{
// storage 정보가 비어 있는 경우
if( m_vecStorageInfo.empty() == true )
return false;
// output 인자 초기화.
ulFhsTotal = 0;
ulFhsAvailable = 0;
iMaxUsage = 0;
// total : 각 mount 의 used + available size 합계.
// available : 각 mount 의 합계.
// 최대 storage 사용률 정보 추출
std::vector< struct stStorageInfo >::iterator it;
for( it = m_vecStorageInfo.begin(); it < m_vecStorageInfo.end(); it++ )
{
// 전체 용량, 사용 가능 용량 합산
ulFhsTotal = ulFhsTotal + it->ulUsedByte + it->ulAvailableByte;
ulFhsAvailable = ulFhsAvailable + it->ulAvailableByte;
// 최대 사용률 정보 추출
if( it->usage > iMaxUsage )
{
iMaxUsage = it->usage;
}
// 2018-02-06 NEW huibong Storage 사용률이 90% 초과하는 경우 해당 Storage 의 정보를 로깅 처리한다.(#31701)
if( it->usage > 90 )
{
_LOG( LINF, "[Storage Info] storage usage: %s %3d %%, used[%14ju], avail[%14ju]."
, it->strName.c_str(), it->usage, it->ulUsedByte, it->ulAvailableByte );
}
else
{
_LOG( LDBG, "%s used[%14ju] avail[%14ju] usage[%3d %%]"
, it->strName.c_str(), it->ulUsedByte, it->ulAvailableByte, it->usage );
}
}
return true;
}
// 멤버 vector 에 저장된 mount 경로명 정보를 반환
bool CStorageInfo::GetStoragePath( std::vector<std::string>& vecPath )
{
// storage 정보가 비어 있는 경우
if( m_vecStorageInfo.empty() == true )
return false;
// output 인자 초기화.
vecPath.clear();
std::vector< struct stStorageInfo >::iterator it;
for( it = m_vecStorageInfo.begin(); it < m_vecStorageInfo.end(); it++ )
{
vecPath.push_back( it->strName );
}
return true;
}
// 멤버 vector 에 저장된 storage 정보 중에 ZFS file system 정보 존재하는지 Check
bool CStorageInfo::IsExistZFS()
{
// storage 정보가 비어 있는 경우 - ZFS file system 없는 것으로 처리
if( m_vecStorageInfo.empty() == true )
return false;
std::vector< struct stStorageInfo >::iterator it;
for( it = m_vecStorageInfo.begin(); it < m_vecStorageInfo.end(); it++ )
{
if( strcasecmp( "zfs", it->strFsTypeName.c_str() ) == 0 )
{
// zfs filesystem 이 존재하는 경우...
// - 나머지는 check 할 필요 없이 그냥 true 반환.
return true;
}
}
// zfs filesystem 이 없는 경우
return false;
}