Beispiel #1
0
static void
on_seafdir_read (OSAsyncResult *res, void *cb_data)
{
    CcnetProcessor *processor = cb_data;
    SeafDir *dir;
    USE_PRIV;

    --(priv->inspect_objects);
    --(priv->checking_dirs);

    if (!res->success) {
        request_object_batch (processor, priv, res->obj_id);
        return;
    }

#ifdef DEBUG
    seaf_debug ("[recvfs] Read seafdir %s.\n", res->obj_id);
#endif

    dir = seaf_dir_from_data (res->obj_id, res->data, res->len,
                              (priv->repo_version > 0));
    if (!dir) {
        seaf_warning ("[recvfs] Corrupt dir object %s.\n", res->obj_id);
        request_object_batch (processor, priv, res->obj_id);
        return;
    }

    int ret = check_seafdir (processor, dir);
    seaf_dir_free (dir);
    if (ret < 0)
        return;
}
Beispiel #2
0
/*
 * Recursively check fs tree rooted at @dir_id. This function returns when
 * all non-existent or invalid objects have been put into data->fetch_objs.
 */
static void
check_seafdir (CcnetProcessor *processor, const char *dir_id)
{
    SeafileGetfsProc *proc = (SeafileGetfsProc *)processor;
    USE_PRIV;
    SeafDir *dir = NULL;
    GList *ptr;
    SeafDirent *dent;

    if (!seaf_fs_manager_object_exists(seaf->fs_mgr, dir_id)) {
        priv->fetch_objs = g_list_prepend (priv->fetch_objs, g_strdup(dir_id));
        return;
    }

    dir = seaf_fs_manager_get_seafdir (seaf->fs_mgr, dir_id);
    if (!dir) {
        /* corrupt dir object */
        priv->fetch_objs = g_list_prepend (priv->fetch_objs, g_strdup(dir_id));
        return;
    }

    for (ptr = dir->entries; ptr; ptr = ptr->next) {
        dent = ptr->data;

        /* Don't check objects that have been checked before. */
        if (g_hash_table_lookup (priv->fs_objects, dent->id))
            continue;

        g_hash_table_insert (priv->fs_objects, g_strdup(dent->id), (gpointer)1);

        if (!seaf_fs_manager_object_exists(seaf->fs_mgr, dent->id)) {
            priv->fetch_objs = g_list_prepend (priv->fetch_objs, g_strdup(dent->id));
            continue;
        }

        if (S_ISDIR(dent->mode)) {
            check_seafdir (processor, dent->id);
        } else if (S_ISREG (dent->mode) && proc->tx_task->is_clone) {
            /* Only check seafile object integrity when clone.
             * This is for the purpose of recovery.
             * In ordinary sync, checking every file object's integrity would
             * take too much CPU time.
             */
            gboolean ok;
            gboolean err = FALSE;
            ok = seaf_fs_manager_verify_seafile (seaf->fs_mgr, dent->id, TRUE, &err);
            if (!ok && !err) {
                seaf_warning ("File object %.8s is corrupt, recover from server.\n",
                              dent->id);
                priv->fetch_objs = g_list_prepend (priv->fetch_objs, g_strdup(dent->id));
            }
        }
    }

    seaf_dir_free (dir);
}
Beispiel #3
0
static void *
check_objects_thread (void *vdata)
{
    CcnetProcessor *processor = vdata;
    USE_PRIV;

    check_seafdir (processor, priv->root_id);

    return vdata;
}
Beispiel #4
0
static int
recv_fs_object (CcnetProcessor *processor, char *content, int clen)
{
    USE_PRIV;
    ObjectPack *pack = (ObjectPack *)content;
    SeafFSObject *fs_obj = NULL;

    if (clen < sizeof(ObjectPack)) {
        seaf_warning ("invalid object id.\n");
        goto bad;
    }

    seaf_debug ("[recvfs] Recv fs object %.8s.\n", pack->id);

    fs_obj = seaf_fs_object_from_data(pack->id,
                                      pack->object, clen - sizeof(ObjectPack),
                                      (priv->repo_version > 0));
    if (!fs_obj) {
        seaf_warning ("Bad fs object %s.\n", pack->id);
        goto bad;
    }

    if (fs_obj->type == SEAF_METADATA_TYPE_DIR) {
        SeafDir *dir = (SeafDir *)fs_obj;
        int ret = check_seafdir (processor, dir);
        if (ret < 0)
            goto bad;
    } else if (fs_obj->type == SEAF_METADATA_TYPE_FILE) {
        /* TODO: check seafile format. */
#if 0
        int ret = seafile_check_data_format (pack->object, clen - 41);
        if (ret < 0) {
            goto bad;
        }
#endif
    }

    seaf_fs_object_free (fs_obj);

    if (save_fs_object (processor, pack, clen) < 0) {
        goto bad;
    }

    return 0;

bad:
    ccnet_processor_send_response (processor, SC_BAD_OBJECT,
                                   SS_BAD_OBJECT, NULL, 0);
    seaf_warning ("[recvfs] Bad fs object received.\n");
    ccnet_processor_done (processor, FALSE);

    seaf_fs_object_free (fs_obj);

    return -1;
}
Beispiel #5
0
static int
recv_fs_object (CcnetProcessor *processor, char *content, int clen)
{
    USE_PRIV;
    ObjectPack *pack = (ObjectPack *)content;
    uint32_t type;

    if (clen < sizeof(ObjectPack)) {
        g_warning ("invalid object id.\n");
        goto bad;
    }

    seaf_debug ("[recvfs] Recv fs object %.8s.\n", pack->id);

    --priv->pending_objects;

    type = seaf_metadata_type_from_data(pack->object, clen);
    if (type == SEAF_METADATA_TYPE_DIR) {
        SeafDir *dir;
        dir = seaf_dir_from_data (pack->id, pack->object, clen - 41);
        if (!dir) {
            g_warning ("Bad directory object %s.\n", pack->id);
            goto bad;
        }
        int ret = check_seafdir (processor, dir);
        seaf_dir_free (dir);
        if (ret < 0)
            goto bad;
    } else if (type == SEAF_METADATA_TYPE_FILE) {
        /* TODO: check seafile format. */
#if 0
        int ret = seafile_check_data_format (pack->object, clen - 41);
        if (ret < 0) {
            goto bad;
        }
#endif
    } else {
        g_warning ("Invalid object type.\n");
        goto bad;
    }

    if (save_fs_object (processor, pack, clen) < 0) {
        goto bad;
    }

    return 0;

bad:
    ccnet_processor_send_response (processor, SC_BAD_OBJECT,
                                   SS_BAD_OBJECT, NULL, 0);
    g_warning ("[recvfs] Bad fs object received.\n");
    ccnet_processor_done (processor, FALSE);

    return -1;
}
Beispiel #6
0
static int
check_object (CcnetProcessor *processor)
{
    USE_PRIV;
    char *obj_id;
    SeafDir *dir;
    static int i = 0;

    request_object_batch_begin(priv);

    /* process inspect queue */
    /* Note: All files in a directory must be checked in an iteration,
     * so we may send out more items than REQUEST_THRESHOLD */
    while (g_hash_table_size (priv->fs_objects) < MAX_NUM_UNREVD) {
        obj_id = (char *) g_queue_pop_head (priv->inspect_queue);
        if (obj_id == NULL)
            break;
        if (!seaf_fs_manager_object_exists(seaf->fs_mgr, obj_id)) {
            request_object_batch (processor, priv, obj_id);
        } else {
            dir = seaf_fs_manager_get_seafdir (seaf->fs_mgr, obj_id);
            if (!dir) {
                /* corrupt dir object */
                request_object_batch (processor, priv, obj_id);
            } else {
                check_seafdir(processor, dir);
                seaf_dir_free (dir);
            }
        }
        g_free (obj_id);        /* free the memory */
    }

    request_object_batch_flush (processor, priv);

    /* check end condition */
    if (i%10 == 0)
        seaf_debug ("[getfs] pending objects num: %d\n", priv->pending_objects);
    ++i;

    if (priv->pending_objects == 0 && g_queue_is_empty(priv->inspect_queue)) {
        ccnet_processor_send_update (processor, SC_END, SS_END, NULL, 0);
        ccnet_processor_done (processor, TRUE);
        return FALSE;
    } else
        return TRUE;
}