153 lines
4.5 KiB
C++
153 lines
4.5 KiB
C++
#include <program/Program.h>
|
|
#include "StorageTkEx.h"
|
|
|
|
#include <sys/xattr.h>
|
|
|
|
#define STORAGETK_FORMAT_XATTR "xattr"
|
|
|
|
|
|
/**
|
|
* Note: Creates the file only if it does not exist yet.
|
|
*
|
|
* @return true if format file was created or existed already
|
|
*/
|
|
bool StorageTkEx::createStorageFormatFile(const std::string pathStr)
|
|
{
|
|
App* app = Program::getApp();
|
|
Config* cfg = app->getConfig();
|
|
|
|
StringMap formatProperties;
|
|
|
|
formatProperties[STORAGETK_FORMAT_XATTR] = cfg->getStoreUseExtendedAttribs() ? "true" : "false";
|
|
|
|
return StorageTk::createStorageFormatFile(pathStr, STORAGETK_FORMAT_CURRENT_VERSION,
|
|
&formatProperties);
|
|
}
|
|
|
|
/**
|
|
* Compatibility and validity check of storage format file contents.
|
|
*
|
|
* @param pathStr path to the main storage working directory (not including a filename)
|
|
* @throws exception if format file was not valid (eg didn't exist or contained wrong version).
|
|
*/
|
|
void StorageTkEx::checkStorageFormatFile(const std::string pathStr)
|
|
{
|
|
App* app = Program::getApp();
|
|
Config* cfg = app->getConfig();
|
|
|
|
StringMap formatProperties;
|
|
StringMapIter formatIter;
|
|
|
|
formatProperties = StorageTk::loadAndUpdateStorageFormatFile(pathStr,
|
|
STORAGETK_FORMAT_MIN_VERSION, STORAGETK_FORMAT_CURRENT_VERSION);
|
|
|
|
formatIter = formatProperties.find(STORAGETK_FORMAT_XATTR);
|
|
if(formatIter == formatProperties.end() )
|
|
{
|
|
throw InvalidConfigException(std::string("Property missing from storage format file: ") +
|
|
STORAGETK_FORMAT_XATTR " (dir: " + pathStr + ")");
|
|
}
|
|
|
|
if(cfg->getStoreUseExtendedAttribs() != StringTk::strToBool(formatIter->second) )
|
|
{
|
|
throw InvalidConfigException("Mismatch of extended attributes settings in storage format file"
|
|
" and daemon config file.");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Note: intended to be used with fsck only.
|
|
* No locks at all at the moment
|
|
*/
|
|
FhgfsOpsErr StorageTkEx::getContDirIDsIncremental(unsigned hashDirNum, bool buddyMirrored,
|
|
int64_t lastOffset, unsigned maxOutEntries, StringList* outContDirIDs, int64_t* outNewOffset)
|
|
{
|
|
const char* logContext = "StorageTkEx (get cont dir ids inc)";
|
|
App* app = Program::getApp();
|
|
|
|
FhgfsOpsErr retVal = FhgfsOpsErr_INTERNAL;
|
|
unsigned numEntries = 0;
|
|
struct dirent* dirEntry = NULL;
|
|
|
|
unsigned firstLevelHashDir;
|
|
unsigned secondLevelHashDir;
|
|
StorageTk::splitHashDirs(hashDirNum, &firstLevelHashDir, &secondLevelHashDir);
|
|
|
|
const Path* dentriesPath =
|
|
buddyMirrored ? app->getBuddyMirrorDentriesPath() : app->getDentriesPath();
|
|
|
|
std::string path = StorageTkEx::getMetaDentriesHashDir(dentriesPath->str(),
|
|
firstLevelHashDir, secondLevelHashDir);
|
|
|
|
DIR* dirHandle = opendir(path.c_str() );
|
|
if(!dirHandle)
|
|
{
|
|
LogContext(logContext).logErr(std::string("Unable to open dentries directory: ") +
|
|
path + ". SysErr: " + System::getErrString() );
|
|
|
|
goto return_res;
|
|
}
|
|
|
|
|
|
errno = 0; // recommended by posix (readdir(3p) )
|
|
|
|
// seek to offset
|
|
seekdir(dirHandle, lastOffset); // (seekdir has no return value)
|
|
|
|
// the actual entry reading
|
|
while ( (numEntries < maxOutEntries) && (dirEntry = StorageTk::readdirFiltered(dirHandle)) )
|
|
{
|
|
std::string dirName = dirEntry->d_name;
|
|
std::string dirID = dirName.substr(0, dirName.length() );
|
|
|
|
*outNewOffset = dirEntry->d_off;
|
|
|
|
// skip root dir if this is not the root MDS
|
|
NumNodeID rootNodeNumID = Program::getApp()->getMetaRoot().getID();
|
|
NumNodeID localNodeNumID = buddyMirrored
|
|
? NumNodeID(Program::getApp()->getMetaBuddyGroupMapper()->getLocalGroupID())
|
|
: Program::getApp()->getLocalNode().getNumID();
|
|
if (unlikely ( (dirID.compare(META_ROOTDIR_ID_STR) == 0) &&
|
|
(localNodeNumID != rootNodeNumID) ))
|
|
continue;
|
|
|
|
outContDirIDs->push_back(dirID);
|
|
numEntries++;
|
|
}
|
|
|
|
if(!dirEntry && errno)
|
|
{
|
|
LogContext(logContext).logErr(std::string("Unable to fetch dentry from: ") +
|
|
path + ". SysErr: " + System::getErrString() );
|
|
}
|
|
else
|
|
{ // all entries read
|
|
retVal = FhgfsOpsErr_SUCCESS;
|
|
}
|
|
|
|
|
|
closedir(dirHandle);
|
|
|
|
return_res:
|
|
return retVal;
|
|
}
|
|
|
|
/**
|
|
* Note: intended to be used with fsck only
|
|
*/
|
|
bool StorageTkEx::getNextContDirID(unsigned hashDirNum, bool buddyMirrored, int64_t lastOffset,
|
|
std::string* outID, int64_t* outNewOffset)
|
|
{
|
|
*outID = "";
|
|
StringList outIDs;
|
|
FhgfsOpsErr retVal = getContDirIDsIncremental(hashDirNum, buddyMirrored, lastOffset, 1, &outIDs,
|
|
outNewOffset);
|
|
if ( ( outIDs.empty() ) || ( retVal != FhgfsOpsErr_SUCCESS ) )
|
|
return false;
|
|
else
|
|
{
|
|
*outID = outIDs.front();
|
|
return true;
|
|
}
|
|
}
|