mirror of
https://github.com/uroni/urbackup_backend.git
synced 2025-10-26 11:36:50 +00:00
215 lines
5.3 KiB
C++
215 lines
5.3 KiB
C++
#include "app.h"
|
|
#include "../../stringtools.h"
|
|
#include "../../Interface/DatabaseCursor.h"
|
|
#include <memory>
|
|
#include "../FileIndex.h"
|
|
#include "../create_files_index.h"
|
|
#include "../dao/ServerBackupDao.h"
|
|
#include "../server_settings.h"
|
|
|
|
|
|
void open_settings_database(bool use_berkeleydb);
|
|
|
|
int check_files_index()
|
|
{
|
|
bool use_berkeleydb;
|
|
open_server_database(use_berkeleydb, true);
|
|
open_settings_database(use_berkeleydb);
|
|
|
|
IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
|
|
if(db==NULL)
|
|
{
|
|
Server->Log("Could not open main database", LL_ERROR);
|
|
return 1;
|
|
}
|
|
|
|
if(db->getEngineName()=="sqlite")
|
|
{
|
|
ServerSettings server_settings(db);
|
|
db->Write("PRAGMA cache_size = -"+nconvert(server_settings.getSettings()->update_stats_cachesize));
|
|
}
|
|
|
|
|
|
IQuery* q_iterate;
|
|
|
|
if(Server->getServerParameter("check_last").empty())
|
|
{
|
|
q_iterate = db->Prepare("SELECT id, shahash, filesize, clientid, fullpath FROM files");
|
|
}
|
|
else
|
|
{
|
|
q_iterate = db->Prepare("SELECT id, shahash, filesize, clientid, fullpath FROM files ORDER BY id DESC LIMIT "+Server->getServerParameter("check_last"));
|
|
}
|
|
|
|
IDatabaseCursor* cursor = q_iterate->Cursor();
|
|
|
|
std::auto_ptr<FileIndex> fileindex(create_lmdb_files_index());
|
|
|
|
if(!fileindex.get())
|
|
{
|
|
Server->Log("Fileindex not present", LL_ERROR);
|
|
return 2;
|
|
}
|
|
|
|
ServerBackupDao backupdao(db);
|
|
|
|
int64 n_checked = 0;
|
|
|
|
bool has_error=false;
|
|
|
|
db_single_result res;
|
|
while(cursor->next(res))
|
|
{
|
|
int64 id = watoi64(res[L"id"]);
|
|
int64 filesize = watoi64(res[L"filesize"]);
|
|
int clientid = watoi(res[L"clientid"]);
|
|
bool found_entry=false;
|
|
|
|
int64 entryid = fileindex->get_with_cache_exact(FileIndex::SIndexKey(reinterpret_cast<const char*>(res[L"shahash"].data()),
|
|
filesize, clientid));
|
|
|
|
if(entryid==0)
|
|
{
|
|
Server->Log(L"Cannot find entry for file with id "+convert(id)+L" with path \""+res[L"fullpath"]+L"\"", LL_ERROR);
|
|
has_error=true;
|
|
continue;
|
|
}
|
|
|
|
int64 found_entryid=entryid;
|
|
|
|
bool first=true;
|
|
|
|
int64 backward_entryid=0;
|
|
int64 prev_entryid=0;
|
|
while(entryid!=0)
|
|
{
|
|
ServerBackupDao::SFindFileEntry fileentry = backupdao.getFileEntry(entryid);
|
|
|
|
//Server->Log("Current entry id="+nconvert(fileentry.id));
|
|
|
|
if(fileentry.id == id)
|
|
{
|
|
found_entry=true;
|
|
}
|
|
|
|
if(clientid!=fileentry.clientid)
|
|
{
|
|
Server->Log(L"First entry with id "+convert(entryid)+L" has wrong clientid (expected: "+convert(clientid)+L" has: "+convert(fileentry.clientid)+L")", LL_ERROR);
|
|
has_error=true;
|
|
}
|
|
|
|
if(first)
|
|
{
|
|
if(!fileentry.pointed_to)
|
|
{
|
|
Server->Log(L"First entry with id "+convert(entryid)+L" does not have pointed_to set to a value unequal 0 ("+convert(fileentry.pointed_to)+L")", LL_ERROR);
|
|
has_error=true;
|
|
}
|
|
backward_entryid=fileentry.next_entry;
|
|
first=false;
|
|
}
|
|
|
|
if(!fileentry.exists)
|
|
{
|
|
Server->Log(L"File entry for file with id "+convert(entryid)+L" in index does not exist in database", LL_ERROR);
|
|
has_error=true;
|
|
break;
|
|
}
|
|
|
|
if(prev_entryid!=0 &&
|
|
fileentry.next_entry!=prev_entryid)
|
|
{
|
|
Server->Log(L"Next entry for file with id "+convert(entryid)+L" is wrong. Assumed="+convert(prev_entryid)+L" Actual="+convert(fileentry.next_entry)+L" Origin="+convert(id), LL_ERROR);
|
|
has_error=true;
|
|
break;
|
|
}
|
|
|
|
if(fileentry.shahash!=res[L"shahash"])
|
|
{
|
|
Server->Log(L"Shahash of entry with id "+convert(entryid)+L" differs from shahash of entry with id "+convert(id)+L". It should not differ.", LL_ERROR);
|
|
has_error=true;
|
|
break;
|
|
}
|
|
|
|
prev_entryid = entryid;
|
|
|
|
entryid = fileentry.prev_entry;
|
|
|
|
if(entryid==0 || prev_entryid==id)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!found_entry)
|
|
{
|
|
entryid = backward_entryid;
|
|
prev_entryid = 0;
|
|
while(entryid!=0)
|
|
{
|
|
ServerBackupDao::SFindFileEntry fileentry = backupdao.getFileEntry(entryid);
|
|
|
|
if(fileentry.id == id)
|
|
{
|
|
found_entry=true;
|
|
}
|
|
|
|
if(!fileentry.exists)
|
|
{
|
|
Server->Log(L"File entry for file with id "+convert(entryid)+L" in index does not exist in database", LL_ERROR);
|
|
has_error=true;
|
|
break;
|
|
}
|
|
|
|
if(prev_entryid!=0 &&
|
|
fileentry.prev_entry!=prev_entryid)
|
|
{
|
|
Server->Log(L"Previous entry for file with id "+convert(entryid)+L" is wrong. Assumed="+convert(prev_entryid)+L" Actual="+convert(fileentry.prev_entry)+L" Origin="+convert(id), LL_ERROR);
|
|
has_error=true;
|
|
break;
|
|
}
|
|
|
|
if(fileentry.shahash!=res[L"shahash"])
|
|
{
|
|
Server->Log(L"Shahash of entry with id "+convert(entryid)+L" differs from shahash of entry with id "+convert(id)+L". It should not differ. -2", LL_ERROR);
|
|
has_error=true;
|
|
break;
|
|
}
|
|
|
|
prev_entryid = entryid;
|
|
|
|
entryid = fileentry.next_entry;
|
|
|
|
if(entryid==0 || prev_entryid==id)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!found_entry)
|
|
{
|
|
Server->Log(L"Entry with id "+convert(id)+L" is not in the list and therefore not indexed by the file entry index. Initial list id is "+convert(found_entryid), LL_ERROR);
|
|
has_error=true;
|
|
}
|
|
|
|
++n_checked;
|
|
|
|
if(n_checked%10000==0)
|
|
{
|
|
Server->Log("Checked "+nconvert(n_checked)+" file entries", LL_INFO);
|
|
}
|
|
}
|
|
|
|
Server->Log("Check complete");
|
|
|
|
if(has_error)
|
|
{
|
|
Server->Log("There were errors.", LL_ERROR);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|