00001
00002
00003
00004
00005
00006
00007
00008 #include "wvautoconf.h"
00009
00010 #ifdef WITH_QDBM
00011
00012 #include "wvondiskhash.h"
00013
00014 extern "C" {
00015 #include <depot.h>
00016 #include <cabin.h>
00017 #include <villa.h>
00018 #include <stdlib.h>
00019 #include <unistd.h>
00020 }
00021
00022
00029 WvQdbmHash::WvQdbmHash(WvStringParm dbfile, bool persist) : dbf(0)
00030 {
00031 saveddata.dptr = 0;
00032 opendb(dbfile, persist);
00033 }
00034
00035
00036 WvQdbmHash::~WvQdbmHash()
00037 {
00038 closedb();
00039 }
00040
00041
00042 void WvQdbmHash::dperr()
00043 {
00044 seterr(dperrmsg(dpecode));
00045 }
00046
00047
00048 void WvQdbmHash::closedb()
00049 {
00050 if (dbf)
00051 {
00052 char *dbfile = vlname((VILLA *) dbf);
00053 if (!vlclose((VILLA *) dbf)) dperr();
00054 if (!persist_dbfile)
00055 vlremove(dbfile);
00056 free(dbfile);
00057 dbf = 0;
00058 }
00059 free((void*)saveddata.dptr);
00060 saveddata.dptr = 0;
00061 seterr("The db is closed.");
00062 }
00063
00064
00065 void WvQdbmHash::opendb(WvStringParm dbfile, bool _persist)
00066 {
00067 static char tmpbuf[] = "/var/tmp/qdbm-annoymousdb-XXXXXX";
00068 static int tmpbuf_inited = 0;
00069 closedb();
00070
00071 noerr();
00072
00073 persist_dbfile = _persist;
00074
00075 if (tmpbuf_inited > 0 && dbfile == WvString(tmpbuf)) {
00076
00077 persist_dbfile = false;
00078 }
00079 else if (dbfile.isnull()) {
00080 persist_dbfile = false;
00081 strcpy(tmpbuf+26, "XXXXXX");
00082 int fd = mkstemp(tmpbuf);
00083 assert(fd != -1);
00084 close(fd);
00085 tmpbuf_inited = 1;
00086 }
00087
00088 int mode = VL_OWRITER | VL_OCREAT;
00089 if (!persist_dbfile) mode |= VL_OTRUNC;
00090
00091
00092
00093
00094 const char *fname = dbfile.isnull() ? tmpbuf : dbfile.cstr();
00095 dbf = vlopen(fname, mode, VL_CMPLEX);
00096 if (dbf == NULL) dperr();
00097 }
00098
00099
00100 void WvQdbmHash::add(const datum &key, const datum &data, bool replace)
00101 {
00102 if (!isok()) return;
00103 int r = vlput((VILLA*)dbf, key.dptr, key.dsize, data.dptr, data.dsize,
00104 replace ? VL_DOVER : VL_DKEEP);
00105
00106 if (!r) dperr();
00107 }
00108
00109
00110 void WvQdbmHash::remove(const datum &key)
00111 {
00112 if (!isok()) return;
00113
00114 if (!vlout((VILLA*)dbf, key.dptr, key.dsize)) dperr();
00115 }
00116
00117
00118 WvQdbmHash::Datum WvQdbmHash::find(const datum &key)
00119 {
00120 free((void*)saveddata.dptr);
00121 saveddata.dptr = NULL;
00122
00123 if (isok())
00124 saveddata.dptr = vlget((VILLA*)dbf, key.dptr, key.dsize,
00125 &saveddata.dsize);
00126
00127 return saveddata;
00128 }
00129
00130
00131 bool WvQdbmHash::exists(const datum &key)
00132 {
00133 if (!isok()) return false;
00134 return vlvnum((VILLA*)dbf, key.dptr, key.dsize);
00135 }
00136
00137
00138 void WvQdbmHash::zap()
00139 {
00140 if (!dbf)
00141 return;
00142
00143 char *name = vlname((VILLA*)dbf);
00144 closedb();
00145 vlremove(name);
00146 opendb(name);
00147 free(name);
00148 }
00149
00150
00151 void WvQdbmHash::IterBase::next(datum &curkey, datum &curdata)
00152 {
00153
00154
00155
00156 if (!parent.isok())
00157 return;
00158
00159 VILLA *dbf = (VILLA*)parent.dbf;
00160 Datum wanted = { 0, 0 };
00161
00162 int ret;
00163 if (curkey.dptr)
00164 {
00165
00166
00167
00168 wanted.dsize = curkey.dsize;
00169 wanted.dptr = (typeof(wanted.dptr))malloc(wanted.dsize);
00170 memcpy((void*)wanted.dptr, curkey.dptr, wanted.dsize);
00171 ret = vlcurjump(dbf, curkey.dptr, curkey.dsize, VL_JFORWARD);
00172 }
00173 else if (rewindto.dptr)
00174 ret = vlcurjump(dbf, rewindto.dptr, rewindto.dsize, VL_JFORWARD);
00175 else
00176 ret = vlcurfirst(dbf);
00177
00178 if (!ret) goto DONE;
00179
00180
00181 curkey.dptr = vlcurkey((VILLA*)parent.dbf, &curkey.dsize);
00182 if (!curkey.dptr) goto DONE;
00183
00184
00185 if (wanted.dptr && wanted.dsize == curkey.dsize
00186 && !memcmp(wanted.dptr, curkey.dptr, wanted.dsize))
00187 {
00188
00189
00190 if (vlcurnext(dbf))
00191 curkey.dptr = vlcurkey((VILLA*)parent.dbf, &curkey.dsize);
00192 else
00193 curkey.dptr = NULL;
00194
00195
00196
00197 }
00198
00199
00200 if (curkey.dptr)
00201 curdata = parent.find(curkey);
00202
00203 DONE:
00204 free((void*)wanted.dptr);
00205
00206
00207 }
00208
00209 #endif