1
0
mirror of https://github.com/haiwen/seafile-server.git synced 2025-06-27 23:46:48 +00:00
seafile-server/server/gc/verify.c

161 lines
4.3 KiB
C
Raw Normal View History

2016-08-10 06:53:33 +00:00
#include "seafile-session.h"
#include "log.h"
typedef struct VerifyData {
SeafRepo *repo;
gint64 truncate_time;
gboolean traversed_head;
} VerifyData;
static int
check_blocks (VerifyData *data, const char *file_id)
{
SeafRepo *repo = data->repo;
Seafile *seafile;
int i;
seafile = seaf_fs_manager_get_seafile (seaf->fs_mgr,
repo->store_id,
repo->version,
file_id);
if (!seafile) {
seaf_warning ("Failed to find file %s.\n", file_id);
return -1;
}
for (i = 0; i < seafile->n_blocks; ++i) {
if (!seaf_block_manager_block_exists (seaf->block_mgr,
repo->store_id,
repo->version,
seafile->blk_sha1s[i]))
g_message ("Block %s is missing.\n", seafile->blk_sha1s[i]);
}
seafile_unref (seafile);
return 0;
}
static gboolean
fs_callback (SeafFSManager *mgr,
const char *store_id,
int version,
const char *obj_id,
int type,
void *user_data,
gboolean *stop)
{
VerifyData *data = user_data;
if (type == SEAF_METADATA_TYPE_FILE && check_blocks (data, obj_id) < 0)
return FALSE;
return TRUE;
}
static gboolean
traverse_commit (SeafCommit *commit, void *vdata, gboolean *stop)
{
VerifyData *data = vdata;
SeafRepo *repo = data->repo;
int ret;
if (data->truncate_time == 0)
{
*stop = TRUE;
/* Stop after traversing the head commit. */
}
else if (data->truncate_time > 0 &&
(gint64)(commit->ctime) < data->truncate_time &&
data->traversed_head)
{
*stop = TRUE;
return TRUE;
}
if (!data->traversed_head)
data->traversed_head = TRUE;
ret = seaf_fs_manager_traverse_tree (seaf->fs_mgr,
repo->store_id,
repo->version,
commit->root_id,
fs_callback,
vdata, FALSE);
if (ret < 0)
return FALSE;
return TRUE;
}
static int
verify_repo (SeafRepo *repo)
{
GList *branches, *ptr;
SeafBranch *branch;
int ret = 0;
VerifyData data = {0};
data.repo = repo;
data.truncate_time = seaf_repo_manager_get_repo_truncate_time (repo->manager,
repo->id);
branches = seaf_branch_manager_get_branch_list (seaf->branch_mgr, repo->id);
if (branches == NULL) {
seaf_warning ("[GC] Failed to get branch list of repo %s.\n", repo->id);
return -1;
}
for (ptr = branches; ptr != NULL; ptr = ptr->next) {
branch = ptr->data;
gboolean res = seaf_commit_manager_traverse_commit_tree (seaf->commit_mgr,
repo->id,
repo->version,
branch->commit_id,
traverse_commit,
&data, FALSE);
seaf_branch_unref (branch);
if (!res) {
ret = -1;
break;
}
}
g_list_free (branches);
return ret;
}
int
verify_repos (GList *repo_id_list)
{
if (repo_id_list == NULL)
repo_id_list = seaf_repo_manager_get_repo_id_list (seaf->repo_mgr);
GList *ptr;
SeafRepo *repo;
int ret = 0;
for (ptr = repo_id_list; ptr != NULL; ptr = ptr->next) {
repo = seaf_repo_manager_get_repo_ex (seaf->repo_mgr, (const gchar *)ptr->data);
g_free (ptr->data);
if (!repo)
continue;
if (repo->is_corrupted) {
seaf_warning ("Repo %s is corrupted.\n", repo->id);
} else {
ret = verify_repo (repo);
seaf_repo_unref (repo);
if (ret < 0)
break;
}
}
g_list_free (repo_id_list);
return ret;
}