]> mj.ucw.cz Git - libucw.git/blob - lib/db-tool.c
db-rebuild replaced by db-tool which allows not only database
[libucw.git] / lib / db-tool.c
1 /*
2  *      SDBM Database Utility
3  *
4  *      (c) 2000--2001 Martin Mares <mj@ucw.cz>
5  */
6
7 #include "lib/lib.h"
8 #include "lib/db.h"
9 #include "lib/db_internal.h"
10 #include "lib/fastbuf.h"
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17 #include <errno.h>
18 #include <getopt.h>
19
20 static int verbose=0;
21 static int cache=1024;
22 static int force_key=-2;
23 static int force_val=-2;
24 static int force_page=-1;
25
26 #define SDBM_DUMP_MAGIC 0x321f120e
27 #define SDBM_DUMP_VERSION 1
28
29 static void
30 dump(char *db, char *dmp)
31 {
32   struct sdbm *src;
33   struct fastbuf *dest;
34   struct sdbm_options op;
35   int e, c=0;
36
37   bzero(&op, sizeof(op));
38   op.name = db;
39   op.cache_size = 16;
40   op.flags = 0;
41   src = sdbm_open(&op);
42   if (!src)
43     die("Source open failed: %m");
44
45   dest = bopen(dmp, O_WRONLY | O_CREAT | O_TRUNC, 65536);
46   bputl(dest, SDBM_DUMP_MAGIC);
47   bputl(dest, SDBM_DUMP_VERSION);
48   bputl(dest, src->page_order);
49   bputl(dest, src->key_size);
50   bputl(dest, src->val_size);
51
52   fprintf(stderr, "Dumping database...\n");
53   sdbm_rewind(src);
54   for(;;)
55     {
56       byte key[65536], val[65536];
57       int klen = sizeof(key);
58       int vlen = sizeof(val);
59       e = sdbm_get_next(src, key, &klen, val, &vlen);
60       if (!e)
61         break;
62       if (e < 0)
63         fprintf(stderr, "sdbm_get_next: error %d\n", e);
64       if (!(c++ % 1024))
65         {
66           fprintf(stderr, "%d\r", c);
67           fflush(stderr);
68         }
69       bputw(dest, klen);
70       bwrite(dest, key, klen);
71       bputw(dest, vlen);
72       bwrite(dest, val, vlen);
73     }
74
75   sdbm_close(src);
76   bclose(dest);
77   fprintf(stderr, "Dumped %d records\n", c);
78 }
79
80 static void
81 restore(char *dmp, char *db)
82 {
83   struct sdbm *dest;
84   struct fastbuf *src;
85   struct sdbm_options op;
86   int e, c=0;
87
88   src = bopen(dmp, O_RDONLY, 65536);
89   if (bgetl(src) != SDBM_DUMP_MAGIC ||
90       bgetl(src) != SDBM_DUMP_VERSION)
91     die("%s: not a sdbm dump", dmp);
92
93   bzero(&op, sizeof(op));
94   op.name = db;
95   e = unlink(op.name);
96   if (e < 0 && errno != ENOENT)
97     die("unlink: %m");
98   op.cache_size = cache;
99   op.flags = SDBM_CREAT | SDBM_WRITE | SDBM_FAST;
100   op.page_order = bgetl(src);
101   if (force_page >= 0)
102     op.page_order = force_page;
103   op.key_size = bgetl(src);
104   if (force_key >= 0)
105     op.key_size = force_key;
106   op.val_size = bgetl(src);
107   if (force_val >= 0)
108     op.val_size = force_val;
109   dest = sdbm_open(&op);
110   if (!dest)
111     die("Destination open failed");
112
113   fprintf(stderr, "Restoring database...\n");
114   for(;;)
115     {
116       byte key[65536], val[65536];
117       int klen, vlen;
118       klen = bgetw(src);
119       if (klen < 0)
120         break;
121       breadb(src, key, klen);
122       vlen = bgetw(src);
123       if (vlen < 0)
124         die("Corrupted dump file: value missing");
125       breadb(src, val, vlen);
126       if (!(c++ % 1024))
127         {
128           fprintf(stderr, "%d\r", c);
129           fflush(stderr);
130         }
131       if (sdbm_store(dest, key, klen, val, vlen) == 0)
132         fprintf(stderr, "sdbm_store: duplicate key\n");
133     }
134
135   bclose(src);
136   sdbm_close(dest);
137   fprintf(stderr, "Restored %d records\n", c);
138 }
139
140 static void
141 rebuild(char *sdb, char *ddb)
142 {
143   struct sdbm *src, *dest;
144   struct sdbm_options op;
145   int e, c=0;
146
147   bzero(&op, sizeof(op));
148   op.name = sdb;
149   op.cache_size = 16;
150   op.flags = 0;
151   src = sdbm_open(&op);
152   if (!src)
153     die("Source open failed: %m");
154
155   op.name = ddb;
156   e = unlink(op.name);
157   if (e < 0 && errno != ENOENT)
158     die("unlink: %m");
159   op.cache_size = cache;
160   op.flags = SDBM_CREAT | SDBM_WRITE | SDBM_FAST;
161   op.page_order = (force_page >= 0) ? force_page : src->root->page_order;
162   op.key_size = (force_key >= -1) ? force_key : src->root->key_size;
163   op.val_size = (force_val >= -1) ? force_val : src->root->val_size;
164   dest = sdbm_open(&op);
165   if (!dest)
166     die("Destination open failed");
167
168   fprintf(stderr, "Rebuilding database...\n");
169   sdbm_rewind(src);
170   for(;;)
171     {
172       byte key[65536], val[65536];
173       int klen = sizeof(key);
174       int vlen = sizeof(val);
175       e = sdbm_get_next(src, key, &klen, val, &vlen);
176       if (!e)
177         break;
178       if (e < 0)
179         fprintf(stderr, "sdbm_get_next: error %d\n", e);
180       if (!(c++ % 1024))
181         {
182           fprintf(stderr, "%d\r", c);
183           fflush(stderr);
184         }
185       if (sdbm_store(dest, key, klen, val, vlen) == 0)
186         fprintf(stderr, "sdbm_store: duplicate key\n");
187     }
188
189   sdbm_close(src);
190   sdbm_close(dest);
191   fprintf(stderr, "Copied %d records\n", c);
192 }
193
194 int
195 main(int argc, char **argv)
196 {
197   int o;
198
199   while ((o = getopt(argc, argv, "vc:k:d:p:")) >= 0)
200     switch (o)
201       {
202       case 'v':
203         verbose++;
204         break;
205       case 'c':
206         cache=atol(optarg);
207         break;
208       case 'k':
209         force_key=atol(optarg);
210         break;
211       case 'd':
212         force_val=atol(optarg);
213         break;
214       case 'p':
215         force_page=atol(optarg);
216         break;
217       default:
218       bad:
219         fprintf(stderr, "Usage: db-tool [<options>] <command> <database>\n\
220 \n\
221 Options:\n\
222 -v\t\tBe verbose\n\
223 -c<n>\t\tUse cache of <n> pages\n\
224 -d<n>\t\tSet data size to <n> (-1=variable) [restore,rebuild]\n\
225 -k<n>\t\tSet key size to <n> (-1=variable) [restore,rebuild]\n\
226 -p<n>\t\tSet page order to <n> [restore,rebuild]\n\
227 \n\
228 Commands:
229 b <db> <new>\tRebuild database\n\
230 d <db> <dump>\tDump database\n\
231 r <dump> <db>\tRestore database from dump\n\
232 ");
233         return 1;
234       }
235   argc -= optind;
236   argv += optind;
237   if (argc < 1 || strlen(argv[0]) != 1)
238     goto bad;
239
240   switch (argv[0][0])
241     {
242     case 'b':
243       if (argc != 3)
244         goto bad;
245       rebuild(argv[1], argv[2]);
246       break;
247     case 'd':
248       if (argc != 3)
249         goto bad;
250       dump(argv[1], argv[2]);
251       break;
252     case 'r':
253       if (argc != 3)
254         goto bad;
255       restore(argv[1], argv[2]);
256       break;
257     default:
258       goto bad;
259     }
260   return 0;
261 }