/** * Writes the browse host data of the context ``ctx'' to the buffer * ``dest''. This must be called multiple times to retrieve the complete * data until zero is returned i.e., the end of file is reached. * * This routine deals with query hit data generation. * * @param ctx an initialized browse host context. * @param dest the destination buffer. * @param size the amount of bytes ``dest'' can hold. * * @return -1 on failure, zero at the end-of-file condition or if size * was zero. On success, the amount of bytes copied to ``dest'' * is returned. */ static ssize_t browse_host_read_qhits(struct special_upload *ctx, void *const dest, size_t size) { struct browse_host_upload *bh = cast_to_browse_host_upload(ctx); size_t remain = size; char *p = dest; /* * If we have no hit pending that we can send, build some more. */ if (NULL == bh->hits) { pslist_t *files = NULL, *sl; int i; for (i = 0; i < BH_SCAN_AHEAD; i++) { shared_file_t *sf; do { /* Skip holes in indices */ bh->file_index++; sf = shared_file_sorted(bh->file_index); } while (NULL == sf && bh->file_index <= shared_files_scanned()); if (SHARE_REBUILDING == sf || NULL == sf) break; files = pslist_prepend(files, sf); } if (NULL == files) /* Did not find any more file to include */ return 0; /* We're done */ /* * Now build the query hits containing the files we selected. */ files = pslist_reverse(files); /* Preserve order */ if (bh->flags & BH_F_G2) { g2_build_qh2_results(files, i, BH_MAX_QH2_SIZE, browse_host_record_qh2, bh, &blank_guid, 0); } else { qhit_build_results(files, i, BH_MAX_QHIT_SIZE, browse_host_record_hit, bh, &blank_guid, 0, &zero_array); } g_assert(bh->hits != NULL); /* At least 1 hit enqueued */ bh->hits = pslist_reverse(bh->hits); /* Preserve order */ PSLIST_FOREACH(files, sl) { shared_file_t *sf = sl->data; shared_file_unref(&sf); }
/** * Writes the browse host data of the context ``ctx'' to the buffer * ``dest''. This must be called multiple times to retrieve the complete * data until zero is returned i.e., the end of file is reached. * * This routine deals with query hit data generation. * * @param ctx an initialized browse host context. * @param dest the destination buffer. * @param size the amount of bytes ``dest'' can hold. * * @return -1 on failure, zero at the end-of-file condition or if size * was zero. On success, the amount of bytes copied to ``dest'' * is returned. */ static ssize_t browse_host_read_qhits(struct special_upload *ctx, void *const dest, size_t size) { struct browse_host_upload *bh = cast_to_browse_host_upload(ctx); size_t remain = size; char *p = dest; /* * If we have no hit pending that we can send, build some more. */ if (NULL == bh->hits) { GSList *files = NULL; int i; for (i = 0; i < BH_SCAN_AHEAD; i++) { const shared_file_t *sf; do { /* Skip holes in indices */ bh->file_index++; sf = shared_file_sorted(bh->file_index); } while (NULL == sf && bh->file_index <= shared_files_scanned()); if (SHARE_REBUILDING == sf || NULL == sf) break; files = g_slist_prepend(files, deconstify_pointer(sf)); } if (NULL == files) /* Did not find any more file to include */ return 0; /* We're done */ /* * Now build the query hits containing the files we selected. */ files = g_slist_reverse(files); /* Preserve order */ qhit_build_results(files, i, BH_MAX_QHIT_SIZE, browse_host_record_hit, bh, &blank_guid, FALSE, &zero_array); g_assert(bh->hits != NULL); /* At least 1 hit enqueued */ bh->hits = g_slist_reverse(bh->hits); /* Preserve order */ gm_slist_free_null(&files); } /* * Read each query hit in turn. */ while (remain > 0 && NULL != bh->hits) { pmsg_t *mb = bh->hits->data; int r; r = pmsg_read(mb, p, remain); p += r; remain -= r; if (r == 0 || 0 == pmsg_size(mb)) { bh->hits = g_slist_remove(bh->hits, mb); pmsg_free(mb); } } return size - remain; }