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