]> mj.ucw.cz Git - libucw.git/blob - lib/sorter/sbuck.c
Cannot swap out the source file, because we don't know how to reopen it.
[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/sorter/common.h"
14
15 #include <fcntl.h>
16
17 void *
18 sorter_alloc(struct sort_context *ctx, uns size)
19 {
20   return mp_alloc_zero(ctx->pool, size);
21 }
22
23 struct sort_bucket *
24 sbuck_new(struct sort_context *ctx)
25 {
26   struct sort_bucket *b = sorter_alloc(ctx, sizeof(struct sort_bucket));
27   b->ctx = ctx;
28   return b;
29 }
30
31 void
32 sbuck_drop(struct sort_bucket *b)
33 {
34   if (b)
35     {
36       ASSERT(!(b->flags & SBF_DESTROYED));
37       if (b->n.prev)
38         clist_remove(&b->n);
39       bclose(b->fb);
40       bzero(b, sizeof(*b));
41       b->flags = SBF_DESTROYED;
42     }
43 }
44
45 sh_off_t
46 sbuck_size(struct sort_bucket *b)
47 {
48   if ((b->flags & SBF_OPEN_WRITE) && !(b->flags & SBF_SWAPPED_OUT))
49     return btell(b->fb);
50   else
51     return b->size;
52 }
53
54 int
55 sbuck_have(struct sort_bucket *b)
56 {
57   return b && sbuck_size(b);
58 }
59
60 int
61 sbuck_has_file(struct sort_bucket *b)
62 {
63   return (b->fb || (b->flags & SBF_SWAPPED_OUT));
64 }
65
66 static void
67 sbuck_swap_in(struct sort_bucket *b)
68 {
69   if (b->flags & SBF_SWAPPED_OUT)
70     {
71       b->fb = bopen(b->filename, O_RDWR, sorter_stream_bufsize);
72       if (b->flags & SBF_OPEN_WRITE)
73         bseek(b->fb, 0, SEEK_END);
74       bconfig(b->fb, BCONFIG_IS_TEMP_FILE, 1);
75       b->flags &= ~SBF_SWAPPED_OUT;
76       SORT_XTRACE(2, "Swapped in %s", b->filename);
77     }
78 }
79
80 struct fastbuf *
81 sbuck_read(struct sort_bucket *b)
82 {
83   sbuck_swap_in(b);
84   if (b->flags & SBF_OPEN_READ)
85     return b->fb;
86   else if (b->flags & SBF_OPEN_WRITE)
87     {
88       b->size = btell(b->fb);
89       b->flags = (b->flags & ~SBF_OPEN_WRITE) | SBF_OPEN_READ;
90       brewind(b->fb);
91       return b->fb;
92     }
93   else
94     ASSERT(0);
95 }
96
97 struct fastbuf *
98 sbuck_write(struct sort_bucket *b)
99 {
100   sbuck_swap_in(b);
101   if (b->flags & SBF_OPEN_WRITE)
102     ASSERT(b->fb);
103   else
104     {
105       ASSERT(!(b->flags & (SBF_OPEN_READ | SBF_DESTROYED)));
106       b->fb = bopen_tmp(sorter_stream_bufsize);
107       if (sorter_debug & SORT_DEBUG_KEEP_BUCKETS)
108         bconfig(b->fb, BCONFIG_IS_TEMP_FILE, 0);
109       b->flags |= SBF_OPEN_WRITE;
110       b->filename = mp_strdup(b->ctx->pool, b->fb->name);
111     }
112   return b->fb;
113 }
114
115 void
116 sbuck_swap_out(struct sort_bucket *b)
117 {
118   if ((b->flags & (SBF_OPEN_READ | SBF_OPEN_WRITE)) && b->fb && !(b->flags & SBF_SOURCE))
119     {
120       if (b->flags & SBF_OPEN_WRITE)
121         b->size = btell(b->fb);
122       bconfig(b->fb, BCONFIG_IS_TEMP_FILE, 0);
123       bclose(b->fb);
124       b->fb = NULL;
125       b->flags |= SBF_SWAPPED_OUT;
126       SORT_XTRACE(2, "Swapped out %s", b->filename);
127     }
128 }
129
130 void
131 sorter_alloc_buf(struct sort_context *ctx)
132 {
133   if (ctx->big_buf)
134     return;
135   u64 bs = MAX(sorter_bufsize/2, 1);
136   bs = ALIGN_TO(bs, (u64)CPU_PAGE_SIZE);
137   ctx->big_buf = big_alloc(2*bs);
138   ctx->big_buf_size = 2*bs;
139   ctx->big_buf_half = ((byte*) ctx->big_buf) + bs;
140   ctx->big_buf_half_size = bs;
141   SORT_XTRACE(2, "Allocated sorting buffer (%jd bytes)", (uintmax_t) bs);
142 }
143
144 void
145 sorter_free_buf(struct sort_context *ctx)
146 {
147   if (!ctx->big_buf)
148     return;
149   big_free(ctx->big_buf, ctx->big_buf_size);
150   ctx->big_buf = NULL;
151   SORT_XTRACE(2, "Freed sorting buffer");
152 }
153
154 void
155 format_size(byte *buf, u64 x)
156 {
157   if (x < 10<<10)
158     sprintf(buf, "%.1fK", (double)x/(1<<10));
159   else if (x < 1<<20)
160     sprintf(buf, "%dK", (int)(x/(1<<10)));
161   else if (x < 10<<20)
162     sprintf(buf, "%.1fM", (double)x/(1<<20));
163   else if (x < 1<<30)
164     sprintf(buf, "%dM", (int)(x/(1<<20)));
165   else if (x < (u64)10<<30)
166     sprintf(buf, "%.1fG", (double)x/(1<<30));
167   else
168     sprintf(buf, "%dG", (int)(x/(1<<30)));
169 }