New upstream version 8.1.0
This commit is contained in:
509
fsck/source/database/FsckDBTable.cpp
Normal file
509
fsck/source/database/FsckDBTable.cpp
Normal file
@@ -0,0 +1,509 @@
|
||||
#include "FsckDBTable.h"
|
||||
|
||||
#include <database/FsckDBException.h>
|
||||
#include <toolkit/FsckTkEx.h>
|
||||
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
static db::DirEntry fsckDirEntryToDbDirEntry(const FsckDirEntry& dentry)
|
||||
{
|
||||
db::DirEntry result = {
|
||||
db::EntryID::fromStr(dentry.getID() ),
|
||||
db::EntryID::fromStr(dentry.getParentDirID() ),
|
||||
|
||||
dentry.getEntryOwnerNodeID().val(),
|
||||
dentry.getInodeOwnerNodeID().val(),
|
||||
|
||||
dentry.getSaveNodeID().val(), dentry.getSaveDevice(), dentry.getSaveInode(),
|
||||
|
||||
{},
|
||||
|
||||
dentry.getInternalID(),
|
||||
|
||||
dentry.getEntryType(),
|
||||
dentry.getName().size() < sizeof(result.name.inlined.text),
|
||||
dentry.getHasInlinedInode(),
|
||||
dentry.getIsBuddyMirrored(),
|
||||
};
|
||||
|
||||
if(result.fileNameInlined) {
|
||||
::memset(result.name.inlined.text, '\0', sizeof(result.name.inlined.text));
|
||||
::strncpy(result.name.inlined.text, dentry.getName().c_str(),
|
||||
sizeof(result.name.inlined.text) - 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void FsckDBDentryTable::insert(FsckDirEntryList& dentries, const BulkHandle* handle)
|
||||
{
|
||||
NameBuffer& names = handle ? *handle->nameBuffer : getNameBuffer(0);
|
||||
|
||||
for(FsckDirEntryListIter it = dentries.begin(), end = dentries.end(); it != end; ++it)
|
||||
{
|
||||
db::DirEntry dentry = fsckDirEntryToDbDirEntry(*it);
|
||||
ByParent link = { dentry.parentDirID, dentry.id, dentry.entryType };
|
||||
|
||||
if(!dentry.fileNameInlined)
|
||||
{
|
||||
dentry.name.extended.fileID = names.id();
|
||||
dentry.name.extended.fileOffset = names.put(it->getName() );
|
||||
}
|
||||
|
||||
if(handle)
|
||||
{
|
||||
handle->dentries->append(dentry);
|
||||
handle->byParent->append(link);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->table.insert(dentry);
|
||||
this->byParent.insert(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FsckDBDentryTable::updateFieldsExceptParent(FsckDirEntryList& dentries)
|
||||
{
|
||||
for(FsckDirEntryListIter it = dentries.begin(), end = dentries.end(); it != end; ++it)
|
||||
{
|
||||
db::DirEntry dentry = fsckDirEntryToDbDirEntry(*it);
|
||||
|
||||
this->table.remove(dentry.pkey() );
|
||||
this->table.insert(dentry);
|
||||
}
|
||||
}
|
||||
|
||||
void FsckDBDentryTable::remove(FsckDirEntryList& dentries)
|
||||
{
|
||||
for(FsckDirEntryListIter it = dentries.begin(), end = dentries.end(); it != end; ++it)
|
||||
this->table.remove(fsckDirEntryToDbDirEntry(*it).pkey() );
|
||||
}
|
||||
|
||||
Table<db::DirEntry>::QueryType FsckDBDentryTable::get()
|
||||
{
|
||||
this->table.commitChanges();
|
||||
return this->table.cursor();
|
||||
}
|
||||
|
||||
Table<FsckDBDentryTable::ByParent>::QueryType FsckDBDentryTable::getByParent()
|
||||
{
|
||||
this->byParent.commitChanges();
|
||||
return this->byParent.cursor();
|
||||
}
|
||||
|
||||
std::pair<bool, db::DirEntry> FsckDBDentryTable::getAnyFor(db::EntryID id)
|
||||
{
|
||||
this->table.commitChanges();
|
||||
|
||||
struct ops
|
||||
{
|
||||
static db::EntryID onlyID(const db::DirEntry::KeyType& key) { return boost::get<0>(key); }
|
||||
};
|
||||
|
||||
return this->table.getByKeyProjection(id, ops::onlyID);
|
||||
}
|
||||
|
||||
std::string FsckDBDentryTable::getNameOf(const db::DirEntry& dentry)
|
||||
{
|
||||
if(dentry.fileNameInlined)
|
||||
return dentry.name.inlined.text;
|
||||
|
||||
return getNameBuffer(dentry.name.extended.fileID).get(dentry.name.extended.fileOffset);
|
||||
}
|
||||
|
||||
std::string FsckDBDentryTable::getPathOf(const db::DirEntry& dentry)
|
||||
{
|
||||
std::string result = getNameOf(dentry);
|
||||
|
||||
db::EntryID parent = dentry.parentDirID;
|
||||
unsigned depth = 0;
|
||||
|
||||
while(!parent.isSpecial() )
|
||||
{
|
||||
depth++;
|
||||
if(depth > 255)
|
||||
return "[<unresolved>]/" + result;
|
||||
|
||||
const NameCacheEntry* cacheEntry = getFromCache(parent);
|
||||
if(cacheEntry)
|
||||
{
|
||||
result = cacheEntry->name + "/" + result;
|
||||
parent = cacheEntry->parent;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::pair<bool, db::DirEntry> item = getAnyFor(parent);
|
||||
if(!item.first)
|
||||
return "[<unresolved>]/" + result;
|
||||
|
||||
std::string parentName = getNameOf(item.second);
|
||||
|
||||
result = parentName + "/" + result;
|
||||
parent = item.second.parentDirID;
|
||||
|
||||
addToCache(item.second, parentName);
|
||||
}
|
||||
|
||||
return getNameOf(parent) + "/" + result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FsckDBFileInodesTable::insert(FsckFileInodeList& fileInodes, const BulkHandle* handle)
|
||||
{
|
||||
for(FsckFileInodeListIter it = fileInodes.begin(), end = fileInodes.end(); it != end; ++it)
|
||||
{
|
||||
const std::vector<uint16_t>& stripes = it->getStripeTargets();
|
||||
|
||||
db::FileInode inode = {
|
||||
db::EntryID::fromStr(it->getID() ),
|
||||
db::EntryID::fromStr(it->getParentDirID() ),
|
||||
db::EntryID::fromStr(it->getPathInfo()->getOrigParentEntryID() ),
|
||||
|
||||
it->getParentNodeID().val(),
|
||||
it->getSaveNodeID().val(),
|
||||
it->getPathInfo()->getOrigUID(),
|
||||
|
||||
it->getUserID(), it->getGroupID(),
|
||||
|
||||
(uint64_t) it->getFileSize(), it->getUsedBlocks(),
|
||||
|
||||
it->getNumHardLinks(),
|
||||
|
||||
it->getSaveInode(),
|
||||
it->getSaveDevice(),
|
||||
|
||||
it->getChunkSize(),
|
||||
|
||||
{},
|
||||
|
||||
it->getIsInlined(),
|
||||
uint32_t(it->getPathInfo()->getFlags() ),
|
||||
it->getStripePatternType(),
|
||||
uint32_t(stripes.size() ),
|
||||
it->getReadable(),
|
||||
it->getIsBuddyMirrored(),
|
||||
it->getIsMismirrored(),
|
||||
};
|
||||
|
||||
db::StripeTargets extraTargets = { inode.id, {}, 0 };
|
||||
|
||||
for(size_t i = 0; i < stripes.size(); i++)
|
||||
{
|
||||
if(i < inode.NTARGETS)
|
||||
inode.targets[i] = stripes[i];
|
||||
else
|
||||
{
|
||||
size_t offsetInPattern = (i - inode.NTARGETS) % extraTargets.NTARGETS;
|
||||
|
||||
if(offsetInPattern == 0)
|
||||
extraTargets.firstTargetIndex = i;
|
||||
|
||||
extraTargets.targets[offsetInPattern] = stripes[i];
|
||||
|
||||
if(offsetInPattern == extraTargets.NTARGETS - 1)
|
||||
{
|
||||
if(handle)
|
||||
std::get<1>(*handle)->append(extraTargets);
|
||||
else
|
||||
this->targets.insert(extraTargets);
|
||||
|
||||
extraTargets.firstTargetIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(handle)
|
||||
{
|
||||
std::get<0>(*handle)->append(inode);
|
||||
if(extraTargets.firstTargetIndex != 0)
|
||||
std::get<1>(*handle)->append(extraTargets);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->inodes.insert(inode);
|
||||
if(extraTargets.firstTargetIndex != 0)
|
||||
this->targets.insert(extraTargets);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FsckDBFileInodesTable::update(FsckFileInodeList& inodes)
|
||||
{
|
||||
for(FsckFileInodeListIter it = inodes.begin(), end = inodes.end(); it != end; ++it)
|
||||
{
|
||||
FsckFileInodeList list(1, *it);
|
||||
|
||||
remove(list);
|
||||
insert(list);
|
||||
}
|
||||
}
|
||||
|
||||
void FsckDBFileInodesTable::remove(FsckFileInodeList& fileInodes)
|
||||
{
|
||||
for(FsckFileInodeListIter it = fileInodes.begin(), end = fileInodes.end(); it != end; ++it)
|
||||
{
|
||||
this->inodes.remove(db::EntryID::fromStr(it->getID() ) );
|
||||
this->targets.remove(db::EntryID::fromStr(it->getID() ) );
|
||||
}
|
||||
}
|
||||
|
||||
FsckDBFileInodesTable::InodesQueryType FsckDBFileInodesTable::getInodes()
|
||||
{
|
||||
this->inodes.commitChanges();
|
||||
return
|
||||
this->inodes.cursor()
|
||||
| db::groupBy(UniqueInlinedInode() )
|
||||
| db::select(SelectFirst() );
|
||||
}
|
||||
|
||||
Table<db::StripeTargets, true>::QueryType FsckDBFileInodesTable::getTargets()
|
||||
{
|
||||
this->targets.commitChanges();
|
||||
return this->targets.cursor();
|
||||
}
|
||||
|
||||
UInt16Vector FsckDBFileInodesTable::getStripeTargetsByKey(const db::EntryID& id)
|
||||
{
|
||||
UInt16Vector allStripeTargets;
|
||||
std::pair<bool, db::FileInode> result = this->get(id.str());
|
||||
|
||||
if (!result.first)
|
||||
return allStripeTargets;
|
||||
|
||||
// firstly copy stripeTargets from FileInode object
|
||||
auto inode = result.second;
|
||||
uint32_t targetArrSize = inode.NTARGETS;
|
||||
uint32_t numTargets = (inode.stripePatternSize > targetArrSize) ? targetArrSize
|
||||
: inode.stripePatternSize;
|
||||
|
||||
std::copy(inode.targets, inode.targets + numTargets, std::back_inserter(allStripeTargets));
|
||||
|
||||
// if extraTargets are present then get them from targets table
|
||||
uint32_t numExtraTargets = inode.stripePatternSize - numTargets;
|
||||
if (numExtraTargets)
|
||||
{
|
||||
this->targets.commitChanges();
|
||||
auto dbRes = this->targets.getAllByKey(id);
|
||||
|
||||
while (dbRes.step())
|
||||
{
|
||||
auto elem = dbRes.get();
|
||||
|
||||
for (int i=0; i<elem->NTARGETS; i++)
|
||||
{
|
||||
allStripeTargets.push_back(elem->targets[i]);
|
||||
numExtraTargets -= 1;
|
||||
if (numExtraTargets == 0) break;
|
||||
}
|
||||
|
||||
if (numExtraTargets == 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
return allStripeTargets;
|
||||
}
|
||||
|
||||
std::pair<bool, db::FileInode> FsckDBFileInodesTable::get(std::string id)
|
||||
{
|
||||
this->inodes.commitChanges();
|
||||
return this->inodes.getByKey(db::EntryID::fromStr(id) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FsckDBDirInodesTable::insert(FsckDirInodeList& dirInodes, const BulkHandle* handle)
|
||||
{
|
||||
for(FsckDirInodeListIter it = dirInodes.begin(), end = dirInodes.end(); it != end; ++it)
|
||||
{
|
||||
db::DirInode inode = {
|
||||
db::EntryID::fromStr(it->getID() ),
|
||||
db::EntryID::fromStr(it->getParentDirID() ),
|
||||
|
||||
it->getParentNodeID().val(),
|
||||
it->getOwnerNodeID().val(),
|
||||
it->getSaveNodeID().val(),
|
||||
|
||||
it->getStripePatternType(),
|
||||
it->getReadable(),
|
||||
it->getIsBuddyMirrored(),
|
||||
it->getIsMismirrored(),
|
||||
|
||||
(uint64_t) it->getSize(),
|
||||
it->getNumHardLinks(),
|
||||
};
|
||||
|
||||
if(handle)
|
||||
(*handle)->append(inode);
|
||||
else
|
||||
this->table.insert(inode);
|
||||
}
|
||||
}
|
||||
|
||||
void FsckDBDirInodesTable::update(FsckDirInodeList& inodes)
|
||||
{
|
||||
for(FsckDirInodeListIter it = inodes.begin(), end = inodes.end(); it != end; ++it)
|
||||
{
|
||||
FsckDirInodeList list(1, *it);
|
||||
|
||||
remove(list);
|
||||
insert(list);
|
||||
}
|
||||
}
|
||||
|
||||
void FsckDBDirInodesTable::remove(FsckDirInodeList& dirInodes)
|
||||
{
|
||||
for(FsckDirInodeListIter it = dirInodes.begin(), end = dirInodes.end(); it != end; ++it)
|
||||
this->table.remove(db::EntryID::fromStr(it->getID() ) );
|
||||
}
|
||||
|
||||
Table<db::DirInode>::QueryType FsckDBDirInodesTable::get()
|
||||
{
|
||||
this->table.commitChanges();
|
||||
return this->table.cursor();
|
||||
}
|
||||
|
||||
std::pair<bool, FsckDirInode> FsckDBDirInodesTable::get(std::string id)
|
||||
{
|
||||
this->table.commitChanges();
|
||||
return this->table.getByKey(db::EntryID::fromStr(id) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
static db::Chunk fsckChunkToDbChunk(FsckChunk& chunk)
|
||||
{
|
||||
db::Chunk result = {
|
||||
db::EntryID::fromStr(chunk.getID() ),
|
||||
chunk.getTargetID(), chunk.getBuddyGroupID(),
|
||||
{},
|
||||
chunk.getFileSize(), chunk.getUsedBlocks(),
|
||||
chunk.getUserID(), chunk.getGroupID(),
|
||||
};
|
||||
|
||||
strncpy(result.savedPath, chunk.getSavedPath()->str().c_str(),
|
||||
sizeof(result.savedPath) - 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void FsckDBChunksTable::insert(FsckChunkList& chunks, const BulkHandle* handle)
|
||||
{
|
||||
for(FsckChunkListIter it = chunks.begin(), end = chunks.end(); it != end; ++it)
|
||||
{
|
||||
if(handle)
|
||||
(*handle)->append(fsckChunkToDbChunk(*it) );
|
||||
else
|
||||
this->table.insert(fsckChunkToDbChunk(*it) );
|
||||
}
|
||||
}
|
||||
|
||||
void FsckDBChunksTable::update(FsckChunkList& chunks)
|
||||
{
|
||||
for(FsckChunkListIter it = chunks.begin(), end = chunks.end(); it != end; ++it)
|
||||
{
|
||||
db::Chunk chunk = fsckChunkToDbChunk(*it);
|
||||
|
||||
this->table.remove(chunk.pkey() );
|
||||
this->table.insert(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
void FsckDBChunksTable::remove(const db::Chunk::KeyType& id)
|
||||
{
|
||||
this->table.remove(id);
|
||||
}
|
||||
|
||||
Table<db::Chunk>::QueryType FsckDBChunksTable::get()
|
||||
{
|
||||
this->table.commitChanges();
|
||||
return this->table.cursor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static db::ContDir fsckContDirToDbContDir(FsckContDir& contDir)
|
||||
{
|
||||
return {
|
||||
db::EntryID::fromStr(contDir.getID()),
|
||||
contDir.getSaveNodeID().val(),
|
||||
contDir.getIsBuddyMirrored(),
|
||||
};
|
||||
}
|
||||
|
||||
void FsckDBContDirsTable::insert(FsckContDirList& contDirs, const BulkHandle* handle)
|
||||
{
|
||||
for(FsckContDirListIter it = contDirs.begin(), end = contDirs.end(); it != end; ++it)
|
||||
{
|
||||
if(handle)
|
||||
(*handle)->append(fsckContDirToDbContDir(*it) );
|
||||
else
|
||||
this->table.insert(fsckContDirToDbContDir(*it) );
|
||||
}
|
||||
}
|
||||
|
||||
Table<db::ContDir>::QueryType FsckDBContDirsTable::get()
|
||||
{
|
||||
this->table.commitChanges();
|
||||
return this->table.cursor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static db::FsID fsckFsIDToDbFsID(FsckFsID& id)
|
||||
{
|
||||
return {
|
||||
db::EntryID::fromStr(id.getID() ),
|
||||
db::EntryID::fromStr(id.getParentDirID() ),
|
||||
id.getSaveNodeID().val(), id.getSaveDevice(), id.getSaveInode(),
|
||||
id.getIsBuddyMirrored(),
|
||||
};
|
||||
}
|
||||
|
||||
void FsckDBFsIDsTable::insert(FsckFsIDList& fsIDs, const BulkHandle* handle)
|
||||
{
|
||||
for(FsckFsIDListIter it = fsIDs.begin(), end = fsIDs.end(); it != end; ++it)
|
||||
{
|
||||
if(handle)
|
||||
(*handle)->append(fsckFsIDToDbFsID(*it) );
|
||||
else
|
||||
this->table.insert(fsckFsIDToDbFsID(*it) );
|
||||
}
|
||||
}
|
||||
|
||||
void FsckDBFsIDsTable::remove(FsckFsIDList& fsIDs)
|
||||
{
|
||||
for(FsckFsIDListIter it = fsIDs.begin(), end = fsIDs.end(); it != end; ++it)
|
||||
this->table.remove(fsckFsIDToDbFsID(*it).pkey() );
|
||||
}
|
||||
|
||||
Table<db::FsID>::QueryType FsckDBFsIDsTable::get()
|
||||
{
|
||||
this->table.commitChanges();
|
||||
return this->table.cursor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FsckDBUsedTargetIDsTable::insert(FsckTargetIDList& targetIDs, const BulkHandle& handle)
|
||||
{
|
||||
for(FsckTargetIDListIter it = targetIDs.begin(), end = targetIDs.end(); it != end; ++it)
|
||||
{
|
||||
db::UsedTarget target = { it->getID(), it->getTargetIDType() };
|
||||
handle->append(target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FsckDBModificationEventsTable::insert(const FsckModificationEventList& events,
|
||||
const BulkHandle& handle)
|
||||
{
|
||||
for(std::list<FsckModificationEvent>::const_iterator it = events.begin(), end = events.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
db::ModificationEvent event = { db::EntryID::fromStr(it->getEntryID() ) };
|
||||
handle->append(event);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user