X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Fsorter%2Fgovern.c;h=738186e34da8a6eebddb0384f6aa3781b4387fcb;hb=bbcbba14a32658a09d7cd44cee40c8369065822f;hp=f962810b3ba0ce72a47d8d63c4f3f8b4b54329eb;hpb=c15baf7b8cf0dc6a07b3c57ad346aee68ac6f19f;p=libucw.git diff --git a/lib/sorter/govern.c b/lib/sorter/govern.c index f962810b..738186e3 100644 --- a/lib/sorter/govern.c +++ b/lib/sorter/govern.c @@ -12,106 +12,10 @@ #include "lib/mempool.h" #include "lib/sorter/common.h" -void * -sorter_alloc(struct sort_context *ctx, uns size) -{ - return mp_alloc_zero(ctx->pool, size); -} - -struct sort_bucket * -sbuck_new(struct sort_context *ctx) -{ - return sorter_alloc(ctx, sizeof(struct sort_bucket)); -} - -void -sbuck_drop(struct sort_bucket *b) -{ - if (b) - { - ASSERT(!(b->flags & SBF_DESTROYED)); - if (b->n.prev) - clist_remove(&b->n); - bclose(b->fb); - bzero(b, sizeof(*b)); - b->flags = SBF_DESTROYED; - } -} - -sh_off_t -sbuck_size(struct sort_bucket *b) -{ - if (b->flags & SBF_OPEN_WRITE) - return btell(b->fb); - else - return b->size; -} - -int -sbuck_have(struct sort_bucket *b) -{ - return b && sbuck_size(b); -} - -struct fastbuf * -sbuck_read(struct sort_bucket *b) -{ - /* FIXME: These functions should handle buckets with no fb and only name. */ - ASSERT(b->fb); - if (b->flags & SBF_OPEN_READ) - return b->fb; - else if (b->flags & SBF_OPEN_WRITE) - { - b->size = btell(b->fb); - b->flags = (b->flags & ~SBF_OPEN_WRITE) | SBF_OPEN_READ; - brewind(b->fb); - return b->fb; - } - else - ASSERT(0); -} - -struct fastbuf * -sbuck_write(struct sort_bucket *b) -{ - if (b->flags & SBF_OPEN_WRITE) - ASSERT(b->fb); - else - { - ASSERT(!(b->flags & (SBF_OPEN_READ | SBF_DESTROYED))); - b->fb = bopen_tmp(sorter_stream_bufsize); - b->flags |= SBF_OPEN_WRITE; - } - return b->fb; -} - -void -sorter_alloc_buf(struct sort_context *ctx) -{ - if (ctx->big_buf) - return; - u64 bs = MAX(sorter_bufsize/2, 1); - bs = ALIGN_TO(bs, (u64)CPU_PAGE_SIZE); - ctx->big_buf = big_alloc(2*bs); - ctx->big_buf_size = 2*bs; - ctx->big_buf_half = ((byte*) ctx->big_buf) + bs; - ctx->big_buf_half_size = bs; - SORT_XTRACE("Allocated sorting buffer (%jd bytes)", (uintmax_t) bs); -} - -void -sorter_free_buf(struct sort_context *ctx) -{ - if (!ctx->big_buf) - return; - big_free(ctx->big_buf, ctx->big_buf_size); - ctx->big_buf = NULL; - SORT_XTRACE("Freed sorting buffer"); -} +#include static int sorter_presort(struct sort_context *ctx, struct sort_bucket *in, struct sort_bucket *out, struct sort_bucket *out_only) { - /* FIXME: Mode with no presorting (mostly for debugging) */ sorter_alloc_buf(ctx); if (in->flags & SBF_CUSTOM_PRESORT) { @@ -124,6 +28,9 @@ static int sorter_presort(struct sort_context *ctx, struct sort_bucket *in, stru static inline struct sort_bucket * sbuck_join_to(struct sort_bucket *b) { + if (sorter_debug & SORT_DEBUG_NO_JOIN) + return NULL; + struct sort_bucket *out = (struct sort_bucket *) b->n.prev; // Such bucket is guaranteed to exist return (out->flags & SBF_FINAL) ? out : NULL; } @@ -131,16 +38,26 @@ sbuck_join_to(struct sort_bucket *b) static void sorter_join(struct sort_bucket *b) { - struct sort_bucket *join = sbuck_join_to(b); - ASSERT(join); - - // FIXME: What if the final bucket doesn't contain any file yet? + struct sort_bucket *join = (struct sort_bucket *) b->n.prev; + ASSERT(join->flags & SBF_FINAL); + ASSERT(b->runs == 1); - SORT_TRACE("Copying %jd bytes to output file", (uintmax_t) sbuck_size(b)); - struct fastbuf *src = sbuck_read(b); - struct fastbuf *dest = sbuck_write(join); - bbcopy(src, dest, ~0U); - sbuck_drop(b); + if (!sbuck_has_file(join)) + { + // The final bucket doesn't have any file associated yet, so replace + // it with the new bucket. + SORT_XTRACE("Replaced final bucket"); + b->flags |= SBF_FINAL; + sbuck_drop(join); + } + else + { + SORT_TRACE("Copying %jd bytes to output file", (uintmax_t) sbuck_size(b)); + struct fastbuf *src = sbuck_read(b); + struct fastbuf *dest = sbuck_write(join); + bbcopy(src, dest, ~0U); + sbuck_drop(b); + } } static void @@ -149,16 +66,14 @@ sorter_twoway(struct sort_context *ctx, struct sort_bucket *b) struct sort_bucket *ins[3] = { NULL }, *outs[3] = { NULL }; cnode *list_pos = b->n.prev; struct sort_bucket *join = sbuck_join_to(b); - if (sorter_debug & SORT_DEBUG_NO_JOIN) - join = NULL; if (!(sorter_debug & SORT_DEBUG_NO_PRESORT) || (b->flags & SBF_CUSTOM_PRESORT)) { SORT_TRACE("Presorting"); ins[0] = sbuck_new(ctx); - sbuck_read(b); if (!sorter_presort(ctx, b, ins[0], join ? : ins[0])) { + SORT_XTRACE("Sorted in memory"); if (join) sbuck_drop(ins[0]); else @@ -238,7 +153,7 @@ sorter_run(struct sort_context *ctx) clist_add_head(&ctx->bucket_list, &bout->n); struct sort_bucket *b; - while (b = clist_next(&ctx->bucket_list, &bout->n)) + while (bout = clist_head(&ctx->bucket_list), b = clist_next(&ctx->bucket_list, &bout->n)) { if (!sbuck_have(b)) sbuck_drop(b); @@ -249,6 +164,7 @@ sorter_run(struct sort_context *ctx) } sorter_free_buf(ctx); + sbuck_write(bout); // Force empty bucket to a file SORT_XTRACE("Final size: %jd", (uintmax_t) sbuck_size(bout)); ctx->out_fb = sbuck_read(bout); }