Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
static gboolean
validate_commit (SeafCommit *commit, void *data, gboolean *stop)
{
    g_message ("Commit %s", commit->commit_id);
    *stop = FALSE;
    if (g_tree_lookup(already_traversed_commits, commit->commit_id)) {
        g_message (" [Skipped]\n");
        return TRUE;
    }
    g_message ("\n");

    if (seaf_fs_manager_traverse_tree
        (seaf->fs_mgr, commit->root_id, validate_block, NULL) < 0) {
        return FALSE;
    }

    char *id = g_strdup(commit->commit_id);
    g_tree_insert (already_traversed_commits, id, id);

    return TRUE;
}
Ejemplo n.º 3
0
static gboolean
traverse_commit (SeafCommit *commit, void *vdata, gboolean *stop)
{
    MigrationData *data = vdata;
    SeafRepo *repo = data->repo;
    int ret;

    if (data->truncate_time > 0 &&
        (gint64)(commit->ctime) < data->truncate_time &&
        data->traversed_head && !data->stop_copy_blocks) {
        data->stop_copy_blocks = TRUE;
    }

    if (!data->traversed_head)
        data->traversed_head = TRUE;

    if (seaf_obj_store_copy_obj (seaf->commit_mgr->obj_store,
                                 repo->id, repo->version,
                                 repo->id, 1,
                                 commit->commit_id) < 0) {
        seaf_warning ("Failed to copy commit %s.\n", commit->commit_id);
        return FALSE;
    }

    ret = seaf_fs_manager_traverse_tree (seaf->fs_mgr,
                                         data->repo->store_id, data->repo->version,
                                         commit->root_id,
                                         fs_callback,
                                         data, FALSE);
    if (ret < 0)
        return FALSE;

    if (data->truncate_time == 0 && !data->stop_copy_blocks) {
        data->stop_copy_blocks = TRUE;
        /* Stop after traversing the head commit. */
    }

    return TRUE;
}
Ejemplo n.º 4
0
static gboolean
check_fs_integrity (SeafCommit *commit, void *vdata, gboolean *stop)
{
    FsckRes *res = vdata;

    /* Stop traversing commits after finding the first consistent commit. */
    if (res->consistent_head != NULL) {
        *stop = TRUE;
        return TRUE;
    }

    int rc = seaf_fs_manager_traverse_tree (seaf->fs_mgr,
                                            res->repo->store_id,
                                            res->repo->version,
                                            commit->root_id,
                                            fs_callback,
                                            res, FALSE);
    if (rc == 0) {
        *stop = TRUE;
        res->consistent_head = g_strdup (commit->commit_id);
    }

    return TRUE;
}
Ejemplo n.º 5
0
static int
recover_corrupted_repo_head (char *repo_id)
{
    GList *commit_list = NULL;
    GList *temp_list = NULL;
    SeafCommit *temp_commit = NULL;
    SeafBranch *branch = NULL;
    SeafRepo *repo = NULL;
    SeafVirtRepo *vinfo = NULL;
    FsckRes res;
    int rc = -1;

    seaf_message ("Recovering corrupt head commit for repo %.8s.\n", repo_id);

    seaf_obj_store_foreach_obj (seaf->commit_mgr->obj_store, repo_id,
                                1, fsck_get_repo_commit, &commit_list);

    if (commit_list == NULL)
        return rc;

    commit_list = g_list_sort (commit_list, compare_commit_by_ctime);
    memset (&res, 0, sizeof(res));
    res.existing_blocks = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                 g_free, NULL);


    for (temp_list = commit_list; temp_list; temp_list = temp_list->next) {
        temp_commit = temp_list->data;

        branch = seaf_branch_new ("master", repo_id, temp_commit->commit_id);
        if (branch == NULL) {
            continue;
        }
        repo = seaf_repo_new (repo_id, NULL, NULL);
        if (repo == NULL) {
            seaf_branch_unref (branch);
            continue;
        }
        repo->head = branch;
        seaf_repo_from_commit (repo, temp_commit);
        vinfo = seaf_repo_manager_get_virtual_repo_info (seaf->repo_mgr, repo_id);
        if (vinfo) {
            repo->is_virtual = TRUE;
            memcpy (repo->store_id, vinfo->origin_repo_id, 36);
        } else {
            repo->is_virtual = FALSE;
            memcpy (repo->store_id, repo->id, 36);
        }
        seaf_virtual_repo_info_free (vinfo);

        res.repo = repo;
        rc = seaf_fs_manager_traverse_tree (seaf->fs_mgr,
                                            repo->store_id,
                                            repo->version,
                                            temp_commit->root_id,
                                            fs_callback,
                                            &res, FALSE);

        if (rc < 0) {
            seaf_repo_unref (repo);
        } else {
            break;
        }
    }

    if (rc < 0) {
        seaf_warning ("Failed to fix head commit of repo %.8s.\n", repo_id);
    } else {
        // create new head commit, and set it's parent commit as latest avaliable commit
        temp_commit = cre_commit_from_parent (repo_id, temp_commit);
        if (temp_commit) {
            seaf_branch_set_commit (repo->head, temp_commit->commit_id);
            // in case of branch col miss, using add_branch instead of update_branch
            if (seaf_branch_manager_add_branch (seaf->branch_mgr, repo->head) < 0) {
                seaf_warning ("Failed to fix head commit of repo %.8s.\n", repo_id);
                rc = -1;
            } else {
                seaf_commit_manager_add_commit (seaf->commit_mgr, temp_commit);
                seaf_message ("Head commit of repo %.8s has been fixed to commit %.8s.\n",
                              repo_id, temp_commit->commit_id);
            }
            seaf_commit_unref (temp_commit);
        } else {
            seaf_warning ("Failed to fix head commit of repo %.8s.\n", repo_id);
            rc = -1;
        }
    }

    g_hash_table_destroy (res.existing_blocks);
    seaf_repo_unref (repo);
    for (temp_list = commit_list; temp_list; temp_list = temp_list->next) {
        temp_commit = temp_list->data;
        seaf_commit_unref (temp_commit);
    }
    g_list_free (commit_list);

    return rc;
}