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; }
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; }
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; }
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; }