]> mj.ucw.cz Git - libucw.git/blob - lib/sorter/sbuck.c
Fix bucket estimator.
[libucw.git] / lib / sorter / sbuck.c
1 /*
2  *      UCW Library -- Universal Sorter: Operations on Contexts, Buffers and Buckets
3  *
4  *      (c) 2007 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include "lib/lib.h"
11 #include "lib/fastbuf.h"
12 #include "lib/mempool.h"
13 #include "lib/stkstring.h"
14 #include "lib/sorter/common.h"
15
16 #include <fcntl.h>
17
18 void *
19 sorter_alloc(struct sort_context *ctx, uns size)
20 {
21   return mp_alloc_zero(ctx->pool, size);
22 }
23
24 struct sort_bucket *
25 sbuck_new(struct sort_context *ctx)
26 {
27   struct sort_bucket *b = sorter_alloc(ctx, sizeof(struct sort_bucket));
28   b->ctx = ctx;
29   return b;
30 }
31
32 void
33 sbuck_drop(struct sort_bucket *b)
34 {
35   if (b)
36     {
37       ASSERT(!(b->flags & SBF_DESTROYED));
38       if (b->n.prev)
39         clist_remove(&b->n);
40       bclose(b->fb);
41       bzero(b, sizeof(*b));
42       b->flags = SBF_DESTROYED;
43     }
44 }
45
46 sh_off_t
47 sbuck_size(struct sort_bucket *b)
48 {
49   if ((b->flags & SBF_OPEN_WRITE) && !(b->flags & SBF_SWAPPED_OUT))
50     return btell(b->fb);
51   else
52     return b->size;
53 }
54
55 int
56 sbuck_have(struct sort_bucket *b)
57 {
58   return b && sbuck_size(b);
59 }
60
61 int
62 sbuck_has_file(struct sort_bucket *b)
63 {
64   return (b->fb || (b->flags & SBF_SWAPPED_OUT));
65 }
66
67 static void
68 sbuck_swap_in(struct sort_bucket *b)
69 {
70   if (b->flags & SBF_SWAPPED_OUT)
71     {
72       if (sorter_stream_bufsize)        /* FIXME: Needs better configuration, probably semi-automatic one */
73         b->fb = bopen(b->filename, O_RDWR, sorter_stream_bufsize);
74       else
75         b->fb = fbdir_open(b->filename, O_RDWR, NULL);
76       if (b->flags & SBF_OPEN_WRITE)
77         bseek(b->fb, 0, SEEK_END);
78       bconfig(b->fb, BCONFIG_IS_TEMP_FILE, 1);
79       b->flags &= ~SBF_SWAPPED_OUT;
80       SORT_XTRACE(2, "Swapped in %s", b->filename);
81     }
82 }
83
84 struct fastbuf *
85 sbuck_read(struct sort_bucket *b)
86 {
87   sbuck_swap_in(b);
88   if (b->flags & SBF_OPEN_READ)
89     return b->fb;
90   else if (b->flags & SBF_OPEN_WRITE)
91     {
92       b->size = btell(b->fb);
93       b->flags = (b->flags & ~SBF_OPEN_WRITE) | SBF_OPEN_READ;
94       brewind(b->fb);
95       return b->fb;
96     }
97   else
98     ASSERT(0);
99 }
100
101 struct fastbuf *
102 sbuck_write(struct sort_bucket *b)
103 {
104   sbuck_swap_in(b);
105   if (b->flags & SBF_OPEN_WRITE)
106     ASSERT(b->fb);
107   else
108     {
109       ASSERT(!(b->flags & (SBF_OPEN_READ | SBF_DESTROYED)));
110       if (sorter_stream_bufsize)
111         b->fb = bopen_tmp(sorter_stream_bufsize);
112       else
113         b->fb = fbdir_open_tmp(NULL);
114       if (sorter_debug & SORT_DEBUG_KEEP_BUCKETS)
115         bconfig(b->fb, BCONFIG_IS_TEMP_FILE, 0);
116       b->flags |= SBF_OPEN_WRITE;
117       b->filename = mp_strdup(b->ctx->pool, b->fb->name);
118     }
119   return b->fb;
120 }
121
122 void
123 sbuck_swap_out(struct sort_bucket *b)
124 {
125   if ((b->flags & (SBF_OPEN_READ | SBF_OPEN_WRITE)) && b->fb && !(b->flags & SBF_SOURCE))
126     {
127       if (b->flags & SBF_OPEN_WRITE)
128         b->size = btell(b->fb);
129       bconfig(b->fb, BCONFIG_IS_TEMP_FILE, 0);
130       bclose(b->fb);
131       b->fb = NULL;
132       b->flags |= SBF_SWAPPED_OUT;
133       SORT_XTRACE(2, "Swapped out %s", b->filename);
134     }
135 }
136
137 void
138 sorter_prepare_buf(struct sort_context *ctx)
139 {
140   u64 bs = MAX(sorter_bufsize/2, 1);
141   bs = ALIGN_TO(bs, (u64)CPU_PAGE_SIZE);
142   ctx->big_buf_size = 2*bs;
143   ctx->big_buf_half_size = bs;
144 }
145
146 void
147 sorter_alloc_buf(struct sort_context *ctx)
148 {
149   if (ctx->big_buf)
150     return;
151   ctx->big_buf = big_alloc(ctx->big_buf_size);
152   ctx->big_buf_half = ((byte*) ctx->big_buf) + ctx->big_buf_half_size;
153   SORT_XTRACE(2, "Allocated sorting buffer (2*%s)", stk_fsize(ctx->big_buf_half_size));
154 }
155
156 void
157 sorter_free_buf(struct sort_context *ctx)
158 {
159   if (!ctx->big_buf)
160     return;
161   big_free(ctx->big_buf, ctx->big_buf_size);
162   ctx->big_buf = NULL;
163   SORT_XTRACE(2, "Freed sorting buffer");
164 }