]> mj.ucw.cz Git - libucw.git/blob - lib/bucket.c
Preliminary version of object bucket code.
[libucw.git] / lib / bucket.c
1 /*
2  *      Sherlock Library -- Object Buckets
3  *
4  *      (c) 2001 Martin Mares <mj@ucw.cz>
5  *
6  *      Warning: Touches internals of the fb-file module!
7  */
8
9 #include "lib/lib.h"
10 #include "lib/bucket.h"
11 #include "lib/fastbuf.h"
12
13 #include <string.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <sys/file.h>
17
18 static int obuck_fd;
19 static struct fastbuf *obuck_fb;
20 static struct obuck_header obuck_hdr;
21 static sh_off_t start_of_this, start_of_next;
22 static char *obuck_name = "db/objects";         /* FIXME */
23
24 void
25 obuck_init(int writeable)
26 {
27   obuck_fb = bopen(obuck_name, (writeable ? O_RDWR | O_CREAT : O_RDONLY), 65536);
28   obuck_fd = obuck_fb->fd;
29 }
30
31 void
32 obuck_cleanup(void)
33 {
34   bclose(obuck_fb);
35 }
36
37 static void
38 obuck_broken(char *msg)
39 {
40   die("Object pool corrupted: %s", msg);        /* FIXME */
41 }
42
43 static inline void
44 obuck_lock_read(void)
45 {
46   flock(obuck_fd, LOCK_SH);
47 }
48
49 static inline void
50 obuck_lock_write(void)
51 {
52   flock(obuck_fd, LOCK_EX);
53 }
54
55 static inline void
56 obuck_unlock(void)
57 {
58   flock(obuck_fd, LOCK_UN);
59 }
60
61 static void
62 obuck_fetch_header(oid_t oid)
63 {
64   start_of_this = ((sh_off_t) oid) << OBUCK_SHIFT;
65   bsetpos(obuck_fb, start_of_this);
66   bread(obuck_fb, &obuck_hdr, sizeof(obuck_hdr));
67   if (obuck_hdr.magic != OBUCK_MAGIC)
68     obuck_broken("Missing magic number");
69   if (obuck_hdr.oid == OBUCK_OID_DELETED)
70     obuck_broken("Access to deleted bucket");
71   if (obuck_hdr.oid != oid)
72     obuck_broken("Invalid backlink");
73 }
74
75 struct fastbuf *
76 obuck_fetch(struct obuck_header *hdrp)
77 {
78   obuck_lock_read();
79   obuck_fetch_header(hdrp->oid);
80   memcpy(hdrp, &obuck_hdr, sizeof(obuck_hdr));
81   return obuck_fb;
82 }
83
84 void
85 obuck_fetch_abort(struct fastbuf *b UNUSED)
86 {
87   obuck_unlock();
88 }
89
90 void
91 obuck_fetch_end(struct fastbuf *b UNUSED)
92 {
93   if (bgetl(b) != OBUCK_TRAILER)
94     obuck_broken("Corrupted trailer");
95   obuck_unlock();
96 }
97
98 struct fastbuf *
99 obuck_write(void)
100 {
101   obuck_lock_write();
102   bseek(obuck_fb, 0, SEEK_END);
103   start_of_this = btell(obuck_fb);
104   if (start_of_this & (OBUCK_ALIGN - 1))
105     obuck_broken("Misaligned file");
106   obuck_hdr.magic = 0;
107   obuck_hdr.oid = start_of_this >> OBUCK_SHIFT;
108   obuck_hdr.length = obuck_hdr.orig_length = 0;
109   bwrite(obuck_fb, &obuck_hdr, sizeof(obuck_hdr));
110   return obuck_fb;
111 }
112
113 void
114 obuck_write_end(struct fastbuf *b UNUSED, struct obuck_header *hdrp)
115 {
116   int pad;
117   obuck_hdr.magic = OBUCK_MAGIC;
118   obuck_hdr.length = obuck_hdr.orig_length = btell(obuck_fb) - start_of_this - sizeof(obuck_hdr);
119   bputl(obuck_fb, OBUCK_TRAILER);
120   pad = (OBUCK_ALIGN - sizeof(obuck_hdr) - obuck_hdr.length - 4) & (OBUCK_ALIGN - 1);
121   while (pad--)
122     bputc(obuck_fb, 0);
123   bflush(obuck_fb);
124   bsetpos(obuck_fb, start_of_this);
125   /* FIXME: Can be replaced with single pwrite */
126   bwrite(obuck_fb, &obuck_hdr, sizeof(obuck_hdr));
127   bflush(obuck_fb);
128   obuck_unlock();
129   memcpy(hdrp, &obuck_hdr, sizeof(obuck_hdr));
130 }
131
132 void
133 obuck_delete(oid_t oid)
134 {
135   obuck_lock_write();
136   obuck_fetch_header(oid);
137   obuck_hdr.oid = OBUCK_OID_DELETED;
138   bflush(obuck_fb);
139   bsetpos(obuck_fb, start_of_this);
140   bwrite(obuck_fb, &obuck_hdr, sizeof(obuck_hdr));
141   bflush(obuck_fb);
142   obuck_unlock();
143 }
144
145 struct fastbuf *
146 obuck_walk_init(void)
147 {
148   start_of_this = start_of_next = 0;
149   obuck_lock_read();
150   return obuck_fb;
151 }
152
153 struct fastbuf *
154 obuck_walk_next(struct fastbuf *b, struct obuck_header *hdrp)
155 {
156   int c;
157
158 restart:
159   start_of_this = start_of_next;
160   bsetpos(b, start_of_this);
161   c = bgetc(b);
162   if (c < 0)
163     return NULL;
164   bungetc(b, c);
165   bread(b, &obuck_hdr, sizeof(obuck_hdr));
166   if (obuck_hdr.magic != OBUCK_MAGIC)
167     obuck_broken("Missing magic number");
168   start_of_next = (start_of_this + sizeof(obuck_hdr) + obuck_hdr.orig_length +
169         4 + OBUCK_ALIGN - 1) & ~((sh_off_t)(OBUCK_ALIGN - 1));
170   if (obuck_hdr.oid == OBUCK_OID_DELETED)
171     goto restart;
172   memcpy(hdrp, &obuck_hdr, sizeof(obuck_hdr));
173   return b;
174 }
175
176 void
177 obuck_walk_end(struct fastbuf *b UNUSED)
178 {
179   obuck_unlock();
180 }
181
182 #ifdef TEST
183 int main(void)
184 {
185   int i, j;
186   struct obuck_header h;
187   struct fastbuf *b;
188   obuck_init(1);
189   for(j=0; j<100; j++)
190     {
191       b = obuck_write();
192       for(i=0; i<100*j; i++)
193         bputc(b, i);
194       obuck_write_end(b, &h);
195       printf("%d\t%08x\t%d\n", j, h.oid, h.orig_length);
196     }
197   obuck_delete(0);
198   b = obuck_walk_init();
199   while (b = obuck_walk_next(b, &h))
200     {
201       printf("<<< %08x\t%d\n", h.oid, h.orig_length);
202     }
203   obuck_walk_end(b);
204   obuck_cleanup();
205   return 0;
206 }
207 #endif