예제 #1
0
파일: seaf-test.c 프로젝트: 2bj/seafile
static int
test_block_manager ()
{
    SeafBlockManager *mgr = seaf->block_mgr;
    char *block_id = "c882e263e9d02c63ca6b61c68508761cbc74c358";
    char wr_buf[1024], rd_buf[1024];
    BlockHandle *handle;
    BlockMetadata *md;
    int n;

    printf ("\n=== Test block manager\n\n");

    memset (wr_buf, 1, sizeof(wr_buf));

    handle = seaf_block_manager_open_block (mgr, block_id, BLOCK_WRITE);
    g_assert (handle != NULL);

    n = seaf_block_manager_write_block (mgr, handle, wr_buf, sizeof(wr_buf));
    g_assert (n == sizeof(wr_buf));

    md = seaf_block_manager_stat_block_by_handle (mgr, handle);
    g_assert (md->size == sizeof(wr_buf));
    g_free (md);

    g_assert (seaf_block_manager_close_block(mgr, handle) == 0);
    g_assert (seaf_block_manager_commit_block(mgr, handle) == 0);

    seaf_block_manager_block_handle_free (mgr, handle);

    handle = seaf_block_manager_open_block (mgr, block_id, BLOCK_READ);
    g_assert (handle != NULL);

    n = seaf_block_manager_read_block (mgr, handle, rd_buf, sizeof(rd_buf));
    g_assert (n == sizeof(rd_buf));

    md = seaf_block_manager_stat_block_by_handle (mgr, handle);
    g_assert (md->size == sizeof(wr_buf));
    g_free (md);

    g_assert (seaf_block_manager_close_block(mgr, handle) == 0);
    seaf_block_manager_block_handle_free (mgr, handle);


    g_assert (memcmp (wr_buf, rd_buf, sizeof(wr_buf)) == 0);

    md = seaf_block_manager_stat_block (mgr, block_id);

    g_assert (strcmp (md->id, block_id) == 0);
    g_assert (md->size == sizeof(wr_buf));

    g_free (md);
    return 0;
}
예제 #2
0
파일: file.c 프로젝트: 90songjian/seafile
int read_file(SeafileSession *seaf, Seafile *file, char *buf, size_t size,
              off_t offset, struct fuse_file_info *info)
{
    BlockHandle *handle = NULL;;
    BlockMetadata *bmd;
    char *blkid;
    char *ptr;
    off_t off = 0, nleft;
    int i, n, ret = -EIO;

    for (i = 0; i < file->n_blocks; i++) {
        blkid = file->blk_sha1s[i];

        bmd = seaf_block_manager_stat_block(seaf->block_mgr, blkid);
        if (!bmd)
            return -EIO;

        if (offset < off + bmd->size) {
            g_free (bmd);
            break;
        }

        off += bmd->size;
        g_free (bmd);
    }

    /* beyond the file size */
    if (i == file->n_blocks)
        return 0;

    nleft = size;
    ptr = buf;
    while (nleft > 0 && i < file->n_blocks) {
        blkid = file->blk_sha1s[i];

        handle = seaf_block_manager_open_block(seaf->block_mgr, blkid, BLOCK_READ);
        if (!handle) {
            seaf_warning ("Failed to open block %s.\n", blkid);
            return -EIO;
        }

        /* trim the offset in a block */
        if (offset > off) {
            char *tmp = (char *)malloc(sizeof(char) * (offset - off));
            if (!tmp)
                return -ENOMEM;

            n = seaf_block_manager_read_block(seaf->block_mgr, handle,
                                              tmp, offset-off);
            if (n != offset - off) {
                seaf_warning ("Failed to read block %s.\n", blkid);
                free (tmp);
                goto out;
            }

            off += n;
            free(tmp);
        }

        if ((n = seaf_block_manager_read_block(seaf->block_mgr,
                                               handle, ptr, nleft)) < 0) {
            seaf_warning ("Failed to read block %s.\n", blkid);
            goto out;
        }

        nleft -= n;
        ptr += n;
        off += n;
        ++i;

        /* At this point we should have read all the content of the block or
         * have read up to @size bytes. So it's safe to close the block.
         */
        seaf_block_manager_close_block(seaf->block_mgr, handle);
        seaf_block_manager_block_handle_free (seaf->block_mgr, handle);
    }

    return size - nleft;

out:
    if (handle) {
        seaf_block_manager_close_block(seaf->block_mgr, handle);
        seaf_block_manager_block_handle_free (seaf->block_mgr, handle);
    }
    return ret;
}
예제 #3
0
static void*
compute_repo_size (void *vjob)
{
    RepoSizeJob *job = vjob;
    Scheduler *sched = job->sched;
    SeafRepo *repo = NULL;
    SeafCommit *head = NULL;
    char *cached_head_id = NULL;
    BlockList *bl;
    char *block_id;
    BlockMetadata *bmd;
    guint64 size = 0;

    repo = seaf_repo_manager_get_repo (sched->seaf->repo_mgr, job->repo_id);
    if (!repo) {
        g_warning ("[scheduler] failed to get repo %s.\n", job->repo_id);
        return vjob;
    }

    cached_head_id = get_cached_head_id (sched->seaf->db, job->repo_id);
    if (g_strcmp0 (cached_head_id, repo->head->commit_id) == 0)
        goto out;

    head = seaf_commit_manager_get_commit (sched->seaf->commit_mgr,
                                           repo->head->commit_id);
    if (!head) {
        g_warning ("[scheduler] failed to get head commit %s.\n",
                   repo->head->commit_id);
        goto out;
    }

    /* Load block list first so that we don't need to count duplicate blocks.
     * We only calculate the size of the head commit.
     */
    bl = block_list_new ();
    if (seaf_fs_manager_populate_blocklist (seaf->fs_mgr,
                                            head->root_id,
                                            bl) < 0) {
        block_list_free (bl);
        goto out;
    }

    int i;
    for (i = 0; i < bl->n_blocks; ++i) {
        block_id = g_ptr_array_index (bl->block_ids, i);
        bmd = seaf_block_manager_stat_block (sched->seaf->block_mgr, block_id);
        if (bmd) {
            size += bmd->size;
            g_free (bmd);
        }
    }
    block_list_free (bl);

    if (set_repo_size (sched->seaf->db,
                       job->repo_id,
                       repo->head->commit_id,
                       size) < 0)
        g_warning ("[scheduler] failed to store repo size %s.\n", job->repo_id);

out:
    seaf_repo_unref (repo);
    seaf_commit_unref (head);
    g_free (cached_head_id);

    return vjob;
}
예제 #4
0
static int
handle_block_header_content_cb (char *content, int clen, void *cbarg)
{
    BlockTxServer *server = cbarg;
    RequestHeader *hdr;

    if (clen != sizeof(RequestHeader)) {
        seaf_warning ("Invalid block request header length %d.\n", clen);
        send_block_response_header (server, STATUS_BAD_REQUEST);
        return -1;
    }

    hdr = (RequestHeader *)content;
    hdr->command = ntohl (hdr->command);

    if (hdr->command != REQUEST_COMMAND_GET &&
        hdr->command != REQUEST_COMMAND_PUT) {
        seaf_warning ("Unknow command %d.\n", hdr->command);
        send_block_response_header (server, STATUS_BAD_REQUEST);
        return -1;
    }

    server->command = hdr->command;
    memcpy (server->curr_block_id, hdr->block_id, 40);

    if (server->command == REQUEST_COMMAND_GET) {
        BlockMetadata *md;
        int block_size;

        seaf_debug ("Received GET request for block %s.\n", server->curr_block_id);

        md = seaf_block_manager_stat_block (seaf->block_mgr,
                                            server->store_id,
                                            server->repo_version,
                                            server->curr_block_id);
        if (!md) {
            seaf_warning ("Failed to stat block %s.\n", server->curr_block_id);
            send_block_response_header (server, STATUS_NOT_FOUND);
            return -1;
        }
        block_size = md->size;
        g_free (md);

        if (send_block_response_header (server, STATUS_OK) < 0)
            return -1;

        if (send_block_content (server, block_size) < 0)
            return -1;

        seaf_debug ("recv_state set to HEADER.\n");

        server->recv_state = RECV_STATE_HEADER;
    } else {
        seaf_debug ("Received PUT request for block %s.\n", server->curr_block_id);

        server->block = seaf_block_manager_open_block (seaf->block_mgr,
                                                       server->store_id,
                                                       server->repo_version,
                                                       server->curr_block_id,
                                                       BLOCK_WRITE);
        if (!server->block) {
            seaf_warning ("Failed to open block %s for write.\n",
                          server->curr_block_id);
            send_block_response_header (server, STATUS_INTERNAL_SERVER_ERROR);
            return -1;
        }

        seaf_debug ("recv_state set to CONTENT.\n");

        server->parser.fragment_cb = save_block_content_cb;
        server->recv_state = RECV_STATE_CONTENT;
    }

    return 0;
}