Mercurial > cpython-lru_cache-weakref
annotate Modules/dbhashmodule.c @ 3044:7e7bb00a0a2e legacy-trunk
Added functionality: locate CW projects, copy them, empty them and
binhex them.
| author | Jack Jansen <jack.jansen@cwi.nl> |
|---|---|
| date | Thu, 31 Aug 1995 13:47:14 +0000 |
| parents | dc6b3e76cce6 |
| children | 65d2d8e67da3 |
| rev | line source |
|---|---|
| 2847 | 1 /*********************************************************** |
| 2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, | |
| 3 The Netherlands. | |
| 4 | |
| 5 All Rights Reserved | |
| 6 | |
| 7 Permission to use, copy, modify, and distribute this software and its | |
| 8 documentation for any purpose and without fee is hereby granted, | |
| 9 provided that the above copyright notice appear in all copies and that | |
| 10 both that copyright notice and this permission notice appear in | |
| 11 supporting documentation, and that the names of Stichting Mathematisch | |
| 12 Centrum or CWI not be used in advertising or publicity pertaining to | |
| 13 distribution of the software without specific, written prior permission. | |
| 14 | |
| 15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO | |
| 16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
| 17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE | |
| 18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
| 19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
| 20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
| 21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
| 22 | |
| 23 ******************************************************************/ | |
| 24 | |
| 25 /* Berkeley DB hash interface. | |
| 26 Author: Michael McLay | |
| 27 Hacked: Guido van Rossum | |
| 28 | |
| 29 XXX To do: | |
| 30 - provide interface to the B-tree and record libraries too | |
| 31 - provide a way to access the various hash functions | |
| 32 - support more open flags | |
| 33 */ | |
| 34 | |
| 35 #include "allobjects.h" | |
| 36 #include "modsupport.h" | |
| 37 | |
| 38 #include <sys/types.h> | |
| 39 #include <sys/stat.h> | |
| 40 #include <fcntl.h> | |
| 41 #include <db.h> | |
| 42 /* Please don't include internal header files of the Berkeley db package | |
| 43 (it messes up the info required in the Setup file) */ | |
| 44 | |
| 45 typedef struct { | |
| 46 OB_HEAD | |
| 47 DB *di_dbhash; | |
| 48 int di_size; /* -1 means recompute */ | |
| 49 } dbhashobject; | |
| 50 | |
| 51 staticforward typeobject Dbhashtype; | |
| 52 | |
| 53 #define is_dbhashobject(v) ((v)->ob_type == &Dbhashtype) | |
| 54 | |
| 55 static object *DbhashError; | |
| 56 | |
| 57 static object * | |
| 58 newdbhashobject(file, flags, mode, | |
| 59 bsize, ffactor, nelem, cachesize, hash, lorder) | |
| 60 char *file; | |
| 61 int flags; | |
| 62 int mode; | |
| 63 int bsize; | |
| 64 int ffactor; | |
| 65 int nelem; | |
| 66 int cachesize; | |
| 67 int hash; /* XXX ignored */ | |
| 68 int lorder; | |
| 69 { | |
| 70 dbhashobject *dp; | |
| 71 HASHINFO info; | |
| 72 | |
| 73 if ((dp = NEWOBJ(dbhashobject, &Dbhashtype)) == NULL) | |
| 74 return NULL; | |
| 75 | |
| 76 info.bsize = bsize; | |
| 77 info.ffactor = ffactor; | |
| 78 info.nelem = nelem; | |
| 79 info.cachesize = cachesize; | |
| 80 info.hash = NULL; /* XXX should derive from hash argument */ | |
| 81 info.lorder = lorder; | |
| 82 | |
| 83 if ((dp->di_dbhash = dbopen(file, flags, mode, DB_HASH, &info)) == NULL) { | |
| 84 err_errno(DbhashError); | |
| 85 DECREF(dp); | |
| 86 return NULL; | |
| 87 } | |
| 88 | |
| 89 dp->di_size = -1; | |
| 90 | |
| 91 return (object *)dp; | |
| 92 } | |
| 93 | |
| 94 static void | |
| 95 dbhash_dealloc(dp) | |
| 96 dbhashobject *dp; | |
| 97 { | |
| 98 if (dp->di_dbhash != NULL) { | |
| 99 if ((dp->di_dbhash->close)(dp->di_dbhash) != 0) | |
| 100 fprintf(stderr, | |
| 101 "Python dbhash: close errno %s in dealloc\n", errno); | |
| 102 } | |
| 103 DEL(dp); | |
| 104 } | |
| 105 | |
| 106 static int | |
| 107 dbhash_length(dp) | |
| 108 dbhashobject *dp; | |
| 109 { | |
| 110 if (dp->di_size < 0) { | |
| 111 DBT krec, drec; | |
| 112 int status; | |
| 113 int size = 0; | |
| 114 for (status = (dp->di_dbhash->seq)(dp->di_dbhash, &krec, &drec,R_FIRST); | |
| 115 status == 0; | |
| 116 status = (dp->di_dbhash->seq)(dp->di_dbhash, &krec, &drec, R_NEXT)) | |
| 117 size++; | |
| 118 if (status < 0) { | |
| 119 err_errno(DbhashError); | |
| 120 return -1; | |
| 121 } | |
| 122 dp->di_size = size; | |
| 123 } | |
| 124 return dp->di_size; | |
| 125 } | |
| 126 | |
| 127 static object * | |
| 128 dbhash_subscript(dp, key) | |
| 129 dbhashobject *dp; | |
| 130 object *key; | |
| 131 { | |
| 132 int status; | |
| 133 object *v; | |
| 134 DBT krec, drec; | |
| 135 char *data; | |
| 136 int size; | |
| 137 | |
| 138 if (!getargs(key, "s#", &data, &size)) | |
| 139 return NULL; | |
| 140 krec.data = data; | |
| 141 krec.size = size; | |
| 142 | |
| 143 status = (dp->di_dbhash->get)(dp->di_dbhash, &krec, &drec, 0); | |
| 144 if (status != 0) { | |
| 145 if (status < 0) | |
| 146 err_errno(DbhashError); | |
| 147 else | |
| 148 err_setval(KeyError, key); | |
| 149 return NULL; | |
| 150 } | |
| 151 | |
| 152 return newsizedstringobject((char *)drec.data, (int)drec.size); | |
| 153 } | |
| 154 | |
| 155 static int | |
| 156 dbhash_ass_sub(dp, key, value) | |
| 157 dbhashobject *dp; | |
| 158 object *key, *value; | |
| 159 { | |
| 160 int status; | |
| 161 DBT krec, drec; | |
| 162 char *data; | |
| 163 int size; | |
| 164 | |
| 165 if (!getargs(key, "s#", &data, &size)) { | |
| 166 err_setstr(TypeError, "dbhash key type must be string"); | |
| 167 return -1; | |
| 168 } | |
| 169 krec.data = data; | |
| 170 krec.size = size; | |
| 171 dp->di_size = -1; | |
| 172 if (value == NULL) { | |
| 173 status = (dp->di_dbhash->del)(dp->di_dbhash, &krec, 0); | |
| 174 } | |
| 175 else { | |
| 176 if (!getargs(value, "s#", &data, &size)) { | |
| 177 err_setstr(TypeError, "dbhash value type must be string"); | |
| 178 return -1; | |
| 179 } | |
| 180 drec.data = data; | |
| 181 drec.size = size; | |
| 182 status = (dp->di_dbhash->put)(dp->di_dbhash, &krec, &drec, 0); | |
| 183 } | |
| 184 if (status != 0) { | |
| 185 if (status < 0) | |
| 186 err_errno(DbhashError); | |
| 187 else | |
| 188 err_setval(KeyError, key); | |
| 189 return -1; | |
| 190 } | |
| 191 return 0; | |
| 192 } | |
| 193 | |
| 194 static mapping_methods dbhash_as_mapping = { | |
| 195 (inquiry)dbhash_length, /*mp_length*/ | |
| 196 (binaryfunc)dbhash_subscript, /*mp_subscript*/ | |
| 197 (objobjargproc)dbhash_ass_sub, /*mp_ass_subscript*/ | |
| 198 }; | |
| 199 | |
| 200 static object * | |
|
2848
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
201 dbhash_close(dp, args) |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
202 dbhashobject *dp; |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
203 object *args; |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
204 { |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
205 if (!getnoarg(args)) |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
206 return NULL; |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
207 if (dp->di_dbhash != NULL) { |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
208 if ((dp->di_dbhash->close)(dp->di_dbhash) != 0) { |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
209 dp->di_dbhash = NULL; |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
210 err_errno(DbhashError); |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
211 return NULL; |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
212 } |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
213 } |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
214 dp->di_dbhash = NULL; |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
215 INCREF(None); |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
216 return None; |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
217 } |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
218 |
|
4f6d5fe19812
fixed arg checking for keys() and close()
Guido van Rossum <guido@python.org>
parents:
2847
diff
changeset
|
219 static object * |
| 2847 | 220 dbhash_keys(dp, args) |
| 221 dbhashobject *dp; | |
| 222 object *args; | |
| 223 { | |
| 224 object *list, *item; | |
| 225 DBT krec, drec; | |
| 226 int status; | |
| 227 int err; | |
| 228 | |
| 229 if (!getnoarg(args)) | |
| 230 return NULL; | |
| 231 list = newlistobject(0); | |
| 232 if (list == NULL) | |
| 233 return NULL; | |
| 234 for (status = (dp->di_dbhash->seq)(dp->di_dbhash, &krec, &drec, R_FIRST); | |
| 235 status == 0; | |
| 236 status = (dp->di_dbhash->seq)(dp->di_dbhash, &krec, &drec, R_NEXT)) { | |
| 237 item = newsizedstringobject((char *)krec.data, (int)krec.size); | |
| 238 if (item == NULL) { | |
| 239 DECREF(list); | |
| 240 return NULL; | |
| 241 } | |
| 242 err = addlistitem(list, item); | |
| 243 DECREF(item); | |
| 244 if (err != 0) { | |
| 245 DECREF(list); | |
| 246 return NULL; | |
| 247 } | |
| 248 } | |
| 249 if (status < 0) { | |
| 250 err_errno(DbhashError); | |
| 251 DECREF(list); | |
| 252 return NULL; | |
| 253 } | |
| 254 if (dp->di_size < 0) | |
| 255 dp->di_size = getlistsize(list); /* We just did the work for this... */ | |
| 256 return list; | |
| 257 } | |
| 258 | |
| 259 static object * | |
| 260 dbhash_has_key(dp, args) | |
| 261 dbhashobject *dp; | |
| 262 object *args; | |
| 263 { | |
| 264 DBT krec, drec; | |
| 265 int status; | |
| 266 char *data; | |
| 267 int size; | |
| 268 | |
| 269 if (!getargs(args, "s#", &data, &size)) | |
| 270 return NULL; | |
| 271 krec.data = data; | |
| 272 krec.size = size; | |
| 273 | |
| 274 status = (dp->di_dbhash->get)(dp->di_dbhash, &krec, &drec, 0); | |
| 275 if (status < 0) { | |
| 276 err_errno(DbhashError); | |
| 277 return NULL; | |
| 278 } | |
| 279 | |
| 280 return newintobject(status == 0); | |
| 281 } | |
| 282 | |
| 283 static struct methodlist dbhash_methods[] = { | |
| 284 {"close", (method)dbhash_close}, | |
| 285 {"keys", (method)dbhash_keys}, | |
| 286 {"has_key", (method)dbhash_has_key}, | |
| 287 {NULL, NULL} /* sentinel */ | |
| 288 }; | |
| 289 | |
| 290 static object * | |
| 291 dbhash_getattr(dp, name) | |
| 292 object *dp; | |
| 293 char *name; | |
| 294 { | |
| 295 return findmethod(dbhash_methods, dp, name); | |
| 296 } | |
| 297 | |
| 298 static typeobject Dbhashtype = { | |
| 299 OB_HEAD_INIT(&Typetype) | |
| 300 0, | |
| 301 "dbhash", | |
| 302 sizeof(dbhashobject), | |
| 303 0, | |
| 304 (destructor)dbhash_dealloc, /*tp_dealloc*/ | |
| 305 0, /*tp_print*/ | |
| 306 (getattrfunc)dbhash_getattr, /*tp_getattr*/ | |
| 307 0, /*tp_setattr*/ | |
| 308 0, /*tp_compare*/ | |
| 309 0, /*tp_repr*/ | |
| 310 0, /*tp_as_number*/ | |
| 311 0, /*tp_as_sequence*/ | |
| 312 &dbhash_as_mapping, /*tp_as_mapping*/ | |
| 313 }; | |
| 314 | |
| 315 static object * | |
| 316 dbhashopen(self, args) | |
| 317 object *self; | |
| 318 object *args; | |
| 319 { | |
| 320 char *file; | |
| 321 char *flag = NULL; | |
| 322 int flags = O_RDONLY; | |
| 323 int mode = 0666; | |
| 324 int bsize = 0; | |
| 325 int ffactor = 0; | |
| 326 int nelem = 0; | |
| 327 int cachesize = 0; | |
| 328 int hash = 0; /* XXX currently ignored */ | |
| 329 int lorder = 0; | |
| 330 | |
| 331 if (!newgetargs(args, "s|siiiiiii", | |
| 332 &file, &flag, &mode, | |
| 333 &bsize, &ffactor, &nelem, &cachesize, &hash, &lorder)) | |
| 334 return NULL; | |
| 335 if (flag != NULL) { | |
| 336 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */ | |
|
2861
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
337 if (flag[0] == 'r') |
| 2847 | 338 flags = O_RDONLY; |
|
2861
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
339 else if (flag[0] == 'w') |
| 2847 | 340 flags = O_RDWR; |
|
2861
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
341 else if (flag[0] == 'c') |
| 2847 | 342 flags = O_RDWR|O_CREAT; |
|
2861
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
343 else if (flag[0] == 'n') |
| 2847 | 344 flags = O_RDWR|O_CREAT|O_TRUNC; |
| 345 else { | |
| 346 err_setstr(DbhashError, | |
|
2861
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
347 "Flag should begin with 'r', 'w', 'c' or 'n'"); |
| 2847 | 348 return NULL; |
| 349 } | |
|
2861
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
350 if (flag[1] == 'l') { |
|
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
351 #if defined(O_EXLOCK) && defined(O_SHLOCK) |
|
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
352 if (flag[0] == 'r') |
|
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
353 flags |= O_SHLOCK; |
|
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
354 else |
|
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
355 flags |= O_EXLOCK; |
|
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
356 #else |
|
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
357 err_setstr(DbhashError, "locking not supported on this platform"); |
|
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
358 return NULL; |
|
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
359 #endif |
|
dc6b3e76cce6
add locking where it exists
Guido van Rossum <guido@python.org>
parents:
2848
diff
changeset
|
360 } |
| 2847 | 361 } |
| 362 return newdbhashobject(file, flags, mode, | |
| 363 bsize, ffactor, nelem, cachesize, hash, lorder); | |
| 364 } | |
| 365 | |
| 366 static struct methodlist dbhashmodule_methods[] = { | |
| 367 {"open", (method)dbhashopen, 1}, | |
| 368 {0, 0}, | |
| 369 }; | |
| 370 | |
| 371 void | |
| 372 initdbhash() { | |
| 373 object *m, *d; | |
| 374 | |
| 375 m = initmodule("dbhash", dbhashmodule_methods); | |
| 376 d = getmoduledict(m); | |
| 377 DbhashError = newstringobject("dbhash.error"); | |
| 378 if (DbhashError == NULL || dictinsert(d, "error", DbhashError)) | |
| 379 fatal("can't define dbhash.error"); | |
| 380 } |
