319 lines
8.5 KiB
C++
319 lines
8.5 KiB
C++
/**
|
|
* @file drive.cpp
|
|
* @brief represent physical drive
|
|
* @author hendrik schutter
|
|
* @date 01.05.2020
|
|
*/
|
|
|
|
#include "../include/reHDD.h"
|
|
using namespace std;
|
|
|
|
// Copy constructor
|
|
Drive::Drive(const Drive &other)
|
|
: state(other.state.load()),
|
|
connectionType(other.connectionType.load()),
|
|
sShredSpeed(other.sShredSpeed.load()),
|
|
bWasShredded(other.bWasShredded),
|
|
bWasShredStarted(other.bWasShredStarted),
|
|
bWasChecked(other.bWasChecked),
|
|
bWasDeleted(other.bWasDeleted),
|
|
bIsOffline(other.bIsOffline),
|
|
u32DriveChecksumAfterShredding(other.u32DriveChecksumAfterShredding),
|
|
sPath(other.sPath),
|
|
u32Timestamp(other.u32Timestamp),
|
|
d32TaskPercentage(other.d32TaskPercentage),
|
|
u32TimestampTaskStart(other.u32TimestampTaskStart),
|
|
u32TaskDuration(other.u32TaskDuration),
|
|
sSmartData(other.sSmartData)
|
|
{
|
|
}
|
|
|
|
// Copy assignment operator
|
|
Drive &Drive::operator=(const Drive &other)
|
|
{
|
|
if (this != &other)
|
|
{
|
|
state = other.state.load();
|
|
connectionType = other.connectionType.load();
|
|
sShredSpeed = other.sShredSpeed.load();
|
|
bWasShredded = other.bWasShredded;
|
|
bWasShredStarted = other.bWasShredStarted;
|
|
bWasChecked = other.bWasChecked;
|
|
bWasDeleted = other.bWasDeleted;
|
|
bIsOffline = other.bIsOffline;
|
|
u32DriveChecksumAfterShredding = other.u32DriveChecksumAfterShredding;
|
|
sPath = other.sPath;
|
|
u32Timestamp = other.u32Timestamp;
|
|
d32TaskPercentage = other.d32TaskPercentage;
|
|
u32TimestampTaskStart = other.u32TimestampTaskStart;
|
|
u32TaskDuration = other.u32TaskDuration;
|
|
sSmartData = other.sSmartData;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
// Move constructor
|
|
Drive::Drive(Drive &&other) noexcept
|
|
: state(other.state.load()),
|
|
connectionType(other.connectionType.load()),
|
|
sShredSpeed(other.sShredSpeed.load()),
|
|
bWasShredded(other.bWasShredded),
|
|
bWasShredStarted(other.bWasShredStarted),
|
|
bWasChecked(other.bWasChecked),
|
|
bWasDeleted(other.bWasDeleted),
|
|
bIsOffline(other.bIsOffline),
|
|
u32DriveChecksumAfterShredding(other.u32DriveChecksumAfterShredding),
|
|
sPath(std::move(other.sPath)),
|
|
u32Timestamp(other.u32Timestamp),
|
|
d32TaskPercentage(other.d32TaskPercentage),
|
|
u32TimestampTaskStart(other.u32TimestampTaskStart),
|
|
u32TaskDuration(other.u32TaskDuration),
|
|
sSmartData(std::move(other.sSmartData))
|
|
{
|
|
}
|
|
|
|
// Move assignment operator
|
|
Drive &Drive::operator=(Drive &&other) noexcept
|
|
{
|
|
if (this != &other)
|
|
{
|
|
state = other.state.load();
|
|
connectionType = other.connectionType.load();
|
|
sShredSpeed = other.sShredSpeed.load();
|
|
bWasShredded = other.bWasShredded;
|
|
bWasShredStarted = other.bWasShredStarted;
|
|
bWasChecked = other.bWasChecked;
|
|
bWasDeleted = other.bWasDeleted;
|
|
bIsOffline = other.bIsOffline;
|
|
u32DriveChecksumAfterShredding = other.u32DriveChecksumAfterShredding;
|
|
sPath = std::move(other.sPath);
|
|
u32Timestamp = other.u32Timestamp;
|
|
d32TaskPercentage = other.d32TaskPercentage;
|
|
u32TimestampTaskStart = other.u32TimestampTaskStart;
|
|
u32TaskDuration = other.u32TaskDuration;
|
|
sSmartData = std::move(other.sSmartData);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
string Drive::getPath(void)
|
|
{
|
|
return sPath;
|
|
}
|
|
|
|
string Drive::getModelFamily(void)
|
|
{
|
|
return sSmartData.sModelFamily;
|
|
}
|
|
|
|
string Drive::getModelName(void)
|
|
{
|
|
return sSmartData.sModelName;
|
|
}
|
|
|
|
string Drive::getSerial(void)
|
|
{
|
|
return sSmartData.sSerial;
|
|
}
|
|
|
|
uint64_t Drive::getCapacity(void)
|
|
{
|
|
return sSmartData.u64Capacity;
|
|
}
|
|
|
|
uint32_t Drive::getErrorCount(void)
|
|
{
|
|
return sSmartData.u32ErrorCount;
|
|
}
|
|
uint32_t Drive::getPowerOnHours(void)
|
|
{
|
|
return sSmartData.u32PowerOnHours;
|
|
}
|
|
|
|
uint32_t Drive::getPowerCycles(void)
|
|
{
|
|
return sSmartData.u32PowerCycles;
|
|
}
|
|
|
|
uint32_t Drive::getTemperature(void)
|
|
{
|
|
return sSmartData.u32Temperature;
|
|
}
|
|
|
|
uint32_t Drive::getReallocatedSectors(void)
|
|
{
|
|
return sSmartData.u32ReallocatedSectors;
|
|
}
|
|
|
|
uint32_t Drive::getPendingSectors(void)
|
|
{
|
|
return sSmartData.u32PendingSectors;
|
|
}
|
|
|
|
uint32_t Drive::getUncorrectableSectors(void)
|
|
{
|
|
return sSmartData.u32UncorrectableSectors;
|
|
}
|
|
|
|
string Drive::sCapacityToText()
|
|
{
|
|
char acBuffer[16];
|
|
double dSize = (double)getCapacity();
|
|
uint16_t u16UnitIndex = 0;
|
|
const char *units[] = {"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
|
|
while (dSize >= 1000) // using the marketing capacity
|
|
{
|
|
dSize /= 1000;
|
|
u16UnitIndex++;
|
|
}
|
|
if (u16UnitIndex >= 9)
|
|
{
|
|
u16UnitIndex = 8;
|
|
}
|
|
int precision = (u16UnitIndex >= 3) ? (u16UnitIndex - 3) : 0;
|
|
sprintf(acBuffer, "%.*f %s", precision, dSize, units[u16UnitIndex]);
|
|
return acBuffer;
|
|
}
|
|
|
|
string Drive::sErrorCountToText()
|
|
{
|
|
return to_string(getErrorCount());
|
|
}
|
|
|
|
string Drive::sPowerOnHoursToText()
|
|
{
|
|
double dDays = 0U;
|
|
double dYears = 0U;
|
|
uint32_t u32Hours = getPowerOnHours();
|
|
stringstream streamDays;
|
|
stringstream streamYears;
|
|
|
|
dDays = (double)((double)u32Hours / (double)24U);
|
|
dYears = (double)((double)u32Hours / (double)8760U);
|
|
|
|
streamDays << fixed << setprecision(0) << dDays;
|
|
streamYears << fixed << setprecision(1) << dYears;
|
|
|
|
string sRet = to_string(getPowerOnHours()) + " hours or " + streamDays.str() + " days or " + streamYears.str() + " years";
|
|
|
|
return sRet;
|
|
}
|
|
|
|
string Drive::sPowerCyclesToText()
|
|
{
|
|
return to_string(getPowerCycles());
|
|
}
|
|
|
|
string Drive::sTemperatureToText()
|
|
{
|
|
return to_string(getTemperature()) + " C";
|
|
}
|
|
|
|
void Drive::setTaskPercentage(double d32TaskPercentage)
|
|
{
|
|
if (d32TaskPercentage <= 100)
|
|
{
|
|
this->d32TaskPercentage = d32TaskPercentage;
|
|
this->setTimestamp(); // set timestamp for this progress for detecting a frozen drive
|
|
}
|
|
}
|
|
double Drive::getTaskPercentage(void)
|
|
{
|
|
return this->d32TaskPercentage;
|
|
}
|
|
|
|
/**
|
|
* \brief set S.M.A.R.T. values in model
|
|
* \param string modelFamily
|
|
* \param string modelName
|
|
* \param string serial
|
|
* \param uint64_t capacity
|
|
* \param uint32_t errorCount
|
|
* \param uint32_t powerOnHours
|
|
* \param uint32_t powerCycle
|
|
* \param uint32_t temperature
|
|
* \return void
|
|
*/
|
|
void Drive::setDriveSMARTData(string modelFamily,
|
|
string modelName,
|
|
string serial,
|
|
uint64_t capacity,
|
|
uint32_t errorCount,
|
|
uint32_t powerOnHours,
|
|
uint32_t powerCycle,
|
|
uint32_t temperature,
|
|
uint32_t reallocatedSectors,
|
|
uint32_t pendingSectors,
|
|
uint32_t uncorrectableSectors)
|
|
{
|
|
this->sSmartData.sModelFamily = modelFamily;
|
|
this->sSmartData.sModelName = modelName;
|
|
this->sSmartData.sSerial = serial;
|
|
this->sSmartData.u64Capacity = capacity;
|
|
this->sSmartData.u32ErrorCount = errorCount;
|
|
this->sSmartData.u32PowerOnHours = powerOnHours;
|
|
this->sSmartData.u32PowerCycles = powerCycle;
|
|
this->sSmartData.u32Temperature = temperature;
|
|
this->sSmartData.u32ReallocatedSectors = reallocatedSectors;
|
|
this->sSmartData.u32PendingSectors = pendingSectors;
|
|
this->sSmartData.u32UncorrectableSectors = uncorrectableSectors;
|
|
}
|
|
|
|
void Drive::setTimestamp()
|
|
{
|
|
if (time(&this->u32Timestamp) == -1)
|
|
{
|
|
// handle error
|
|
this->u32Timestamp = 0U;
|
|
}
|
|
}
|
|
|
|
void Drive::setActionStartTimestamp()
|
|
{
|
|
if (time(&this->u32TimestampTaskStart) == -1)
|
|
{
|
|
// handle error
|
|
this->u32TimestampTaskStart = 0U;
|
|
}
|
|
}
|
|
|
|
time_t Drive::getActionStartTimestamp()
|
|
{
|
|
return this->u32TimestampTaskStart;
|
|
}
|
|
|
|
void Drive::calculateTaskDuration()
|
|
{
|
|
time_t u32localtime;
|
|
if (time(&u32localtime) == -1)
|
|
{
|
|
// handle error
|
|
u32localtime = 0U;
|
|
}
|
|
|
|
this->u32TaskDuration = u32localtime - this->u32TimestampTaskStart;
|
|
}
|
|
|
|
time_t Drive::getTaskDuration()
|
|
{
|
|
return this->u32TaskDuration;
|
|
}
|
|
|
|
void Drive::checkFrozenDrive(void)
|
|
{
|
|
time_t u32localtime;
|
|
time(&u32localtime);
|
|
if (time(&u32localtime) == -1)
|
|
{
|
|
// handle error
|
|
u32localtime = 0U;
|
|
}
|
|
|
|
if ((u32localtime - this->u32Timestamp) >= (FROZEN_TIMEOUT * 60) && (this->u32Timestamp > 0) && (this->getTaskPercentage() < 100.0))
|
|
{
|
|
Logger::logThis()->warning("Drive Frozen: " + this->getModelName() + " " + this->getSerial());
|
|
this->bWasDeleted = false;
|
|
this->bWasShredded = false;
|
|
this->state = Drive::TaskState::FROZEN;
|
|
}
|
|
} |