]> mj.ucw.cz Git - libucw.git/blob - lib/db-emul.c
Split page key to pos and fd. Wastes extra 4 bytes, but simplifies the code a lot.
[libucw.git] / lib / db-emul.c
1 /*
2  *      Sherlock Library -- SDBM emulator at top of GDBM
3  *
4  *      (c) 1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "lib.h"
12 #include "db.h"
13
14 #include <gdbm.h>
15
16 struct sdbm {
17   GDBM_FILE db;
18   datum prevkey;
19 };
20
21 struct sdbm *
22 sdbm_open(struct sdbm_options *o)
23 {
24   struct sdbm *d = xmalloc(sizeof(struct sdbm));
25   d->db = gdbm_open(o->name,
26                     (o->page_order ? (1 << o->page_order) : 0),
27                     ((o->flags & SDBM_WRITE) ? ((o->flags & SDBM_CREAT) ? GDBM_WRCREAT : GDBM_WRITER) : GDBM_READER)
28                       | ((o->flags & SDBM_SYNC) ? GDBM_SYNC : 0),
29                     0666,
30                     NULL);
31   if (o->cache_size)
32     gdbm_setopt(d->db, GDBM_CACHESIZE, &o->cache_size, sizeof(o->cache_size));
33   d->prevkey.dptr = NULL;
34   return d;
35 }
36
37 void
38 sdbm_close(struct sdbm *d)
39 {
40   sdbm_rewind(d);
41   gdbm_close(d->db);
42   free(d);
43 }
44
45 static int
46 sdbm_put_user(byte *D, uns Dl, byte *val, uns *vallen)
47 {
48   if (vallen)
49     {
50       if (*vallen < Dl)
51         return 1;
52       *vallen = Dl;
53     }
54   if (val)
55     memcpy(val, D, Dl);
56   return 0;
57 }
58
59 int
60 sdbm_store(struct sdbm *d, byte *key, uns keylen, byte *val, uns vallen)
61 {
62   datum K, V;
63   int rc;
64
65   K.dptr = key;
66   K.dsize = keylen;
67   V.dptr = val;
68   V.dsize = vallen;
69   rc = gdbm_store(d->db, K, V, GDBM_INSERT);
70   return (rc < 0) ? rc : !rc;
71 }
72
73 int
74 sdbm_replace(struct sdbm *d, byte *key, uns keylen, byte *val, uns vallen)
75 {
76   datum K, V;
77   int rc;
78
79   if (!val)
80     return sdbm_delete(d, key, keylen);
81   K.dptr = key;
82   K.dsize = keylen;
83   V.dptr = val;
84   V.dsize = vallen;
85   rc = gdbm_store(d->db, K, V, GDBM_REPLACE);
86   return (rc < 0) ? rc : !rc;
87 }
88
89 int
90 sdbm_delete(struct sdbm *d, byte *key, uns keylen)
91 {
92   datum K;
93
94   K.dptr = key;
95   K.dsize = keylen;
96   return !gdbm_delete(d->db, K);
97 }
98
99 int
100 sdbm_fetch(struct sdbm *d, byte *key, uns keylen, byte *val, uns *vallen)
101 {
102   datum K, V;
103   int rc;
104
105   K.dptr = key;
106   K.dsize = keylen;
107   if (!val && !vallen)
108     return gdbm_exists(d->db, K);
109   V = gdbm_fetch(d->db, K);
110   if (!V.dptr)
111     return 0;
112   rc = sdbm_put_user(V.dptr, V.dsize, val, vallen);
113   free(V.dptr);
114   return rc ? SDBM_ERROR_TOO_LARGE : 1;
115 }
116
117 void
118 sdbm_rewind(struct sdbm *d)
119 {
120   if (d->prevkey.dptr)
121     {
122       free(d->prevkey.dptr);
123       d->prevkey.dptr = NULL;
124     }
125 }
126
127 int
128 sdbm_get_next(struct sdbm *d, byte *key, uns *keylen, byte *val, uns *vallen)
129 {
130   datum K;
131
132   if (d->prevkey.dptr)
133     {
134       K = gdbm_nextkey(d->db, d->prevkey);
135       free(d->prevkey.dptr);
136     }
137   else
138     K = gdbm_firstkey(d->db);
139   d->prevkey = K;
140   if (!K.dptr)
141     return 0;
142   if (sdbm_put_user(K.dptr, K.dsize, key, keylen))
143     return SDBM_ERROR_TOO_LARGE;
144   if (val || vallen)
145     return sdbm_fetch(d, key, *keylen, val, vallen);
146   return 1;
147 }
148
149 void
150 sdbm_sync(struct sdbm *d)
151 {
152 }