New upstream version 8.1.0
This commit is contained in:
165
storage/source/components/chunkfetcher/ChunkFetcherSlave.cpp
Normal file
165
storage/source/components/chunkfetcher/ChunkFetcherSlave.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
#include "ChunkFetcherSlave.h"
|
||||
|
||||
#include <program/Program.h>
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <libgen.h>
|
||||
|
||||
ChunkFetcherSlave::ChunkFetcherSlave(uint16_t targetID):
|
||||
PThread("ChunkFetcherSlave-" + StringTk::uintToStr(targetID) ),
|
||||
log("ChunkFetcherSlave-" + StringTk::uintToStr(targetID) ),
|
||||
isRunning(false),
|
||||
targetID(targetID)
|
||||
{
|
||||
}
|
||||
|
||||
ChunkFetcherSlave::~ChunkFetcherSlave()
|
||||
{
|
||||
}
|
||||
|
||||
void ChunkFetcherSlave::run()
|
||||
{
|
||||
setIsRunning(true);
|
||||
|
||||
try
|
||||
{
|
||||
registerSignalHandler();
|
||||
|
||||
walkAllChunks();
|
||||
|
||||
log.log(4, "Component stopped.");
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
PThread::getCurrentThreadApp()->handleComponentException(e);
|
||||
}
|
||||
|
||||
setIsRunning(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* walk over all chunks in that target
|
||||
*/
|
||||
void ChunkFetcherSlave::walkAllChunks()
|
||||
{
|
||||
App* app = Program::getApp();
|
||||
|
||||
log.log(Log_DEBUG, "Starting chunks walk...");
|
||||
|
||||
const auto& target = *app->getStorageTargets()->getTargets().at(targetID);
|
||||
|
||||
const auto& targetPath = target.getPath().str();
|
||||
|
||||
// walk over "normal" chunks (i.e. no mirrors)
|
||||
std::string walkPath = targetPath + "/" + CONFIG_CHUNK_SUBDIR_NAME;
|
||||
if(!walkChunkPath(walkPath, 0, walkPath.size() ) )
|
||||
return;
|
||||
|
||||
// let's find out if this target is part of a buddy mirror group and if it is the primary
|
||||
// target; if it is, walk over buddy mirror directory
|
||||
bool isPrimaryTarget;
|
||||
uint16_t buddyGroupID = app->getMirrorBuddyGroupMapper()->getBuddyGroupID(this->targetID,
|
||||
&isPrimaryTarget);
|
||||
|
||||
if (isPrimaryTarget)
|
||||
{
|
||||
walkPath = targetPath + "/" CONFIG_BUDDYMIRROR_SUBDIR_NAME;
|
||||
if(!walkChunkPath(walkPath, buddyGroupID, walkPath.size() ) )
|
||||
return;
|
||||
}
|
||||
|
||||
log.log(Log_DEBUG, "End of chunks walk.");
|
||||
}
|
||||
|
||||
bool ChunkFetcherSlave::walkChunkPath(const std::string& path, uint16_t buddyGroupID,
|
||||
unsigned basePathLen)
|
||||
{
|
||||
DIR* dir = ::opendir(path.c_str() );
|
||||
if(!dir)
|
||||
{
|
||||
LOG(GENERAL, WARNING, "Could not open directory.", path, targetID, sysErr);
|
||||
Program::getApp()->getChunkFetcher()->setBad();
|
||||
return false;
|
||||
}
|
||||
|
||||
int readRes;
|
||||
bool result = true;
|
||||
|
||||
std::string pathBuf = path;
|
||||
pathBuf.push_back('/');
|
||||
|
||||
while(!getSelfTerminate())
|
||||
{
|
||||
::dirent* item;
|
||||
|
||||
// we really want struct struct dirent to contain a reasonably sized array for the filename
|
||||
BOOST_STATIC_ASSERT(sizeof(item->d_name) >= NAME_MAX + 1);
|
||||
|
||||
#if USE_READDIR_R
|
||||
::dirent entry;
|
||||
readRes = ::readdir_r(dir, &entry, &item);
|
||||
#else
|
||||
errno = 0;
|
||||
item = readdir(dir);
|
||||
readRes = item ? 0 : errno;
|
||||
#endif
|
||||
if(readRes != 0)
|
||||
{
|
||||
LOG(GENERAL, WARNING, "readdir failed.", path, targetID, sysErr(readRes));
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!item)
|
||||
break;
|
||||
|
||||
if(::strcmp(item->d_name, ".") == 0 || ::strcmp(item->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
pathBuf.resize(path.size() + 1);
|
||||
pathBuf += item->d_name;
|
||||
|
||||
struct stat statBuf;
|
||||
|
||||
int statRes = ::stat(pathBuf.c_str(), &statBuf);
|
||||
if(statRes)
|
||||
{
|
||||
LOG(GENERAL, WARNING, "Could not stat directory.", ("path", pathBuf), targetID, sysErr);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if(S_ISDIR(statBuf.st_mode) )
|
||||
{
|
||||
result = walkChunkPath(pathBuf, buddyGroupID, basePathLen);
|
||||
if(!result)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* relativeChunkPath = pathBuf.c_str() + basePathLen + 1;
|
||||
|
||||
// get only the dirname part of the path
|
||||
char* tmpPathCopy = strdup(relativeChunkPath);
|
||||
Path savedPath(dirname(tmpPathCopy) );
|
||||
|
||||
free(tmpPathCopy);
|
||||
|
||||
FsckChunk fsckChunk(item->d_name, targetID, savedPath, statBuf.st_size, statBuf.st_blocks,
|
||||
statBuf.st_ctime, statBuf.st_mtime, statBuf.st_atime, statBuf.st_uid, statBuf.st_gid,
|
||||
buddyGroupID);
|
||||
|
||||
Program::getApp()->getChunkFetcher()->addChunk(fsckChunk);
|
||||
}
|
||||
}
|
||||
|
||||
::closedir(dir);
|
||||
|
||||
if (getSelfTerminate())
|
||||
result = false;
|
||||
|
||||
if(!result)
|
||||
Program::getApp()->getChunkFetcher()->setBad();
|
||||
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user