Update of /project/elephant/cvsroot/elephant/src In directory common-lisp.net:/tmp/cvs-serv25807/src
Modified Files: libsleepycat.c Log Message: need to memcpy on writers (alignment) lisp-cmp func, assoc / btree cmp stuff cursor pget, remove key value using cursor length->size
Date: Thu Sep 16 06:18:27 2004 Author: blee
Index: elephant/src/libsleepycat.c diff -u elephant/src/libsleepycat.c:1.7 elephant/src/libsleepycat.c:1.8 --- elephant/src/libsleepycat.c:1.7 Thu Sep 2 16:45:53 2004 +++ elephant/src/libsleepycat.c Thu Sep 16 06:18:27 2004 @@ -39,40 +39,48 @@ ;;; to the Free Software Foundation, Inc., 59 Temple Place, ;;; Suite 330, Boston, MA 02111-1307 USA ;;; -8? +*/
/* Pointer arithmetic utility functions */ - +/* should these be in network-byte order? probably not..... */ int read_int(char *buf, int offset) { - return *(int*)(buf + offset); + int i; + memcpy(&i, buf+offset, sizeof(int)); + return i; }
unsigned int read_uint(char *buf, int offset) { - return *(unsigned int*)(buf + offset); + unsigned int ui; + memcpy(&ui, buf+offset, sizeof(unsigned int)); + return ui; }
float read_float(char *buf, int offset) { - return *(float*)(buf + offset); + float f; + memcpy(&f, buf+offset, sizeof(float)); + return f; }
double read_double(char *buf, int offset) { - return *(double*)(buf + offset); + double d; + memcpy(&d, buf+offset, sizeof(double)); + return d; }
void write_int(char *buf, int num, int offset) { - *(int*)(buf + offset) = num; + memcpy(buf+offset, &num, sizeof(int)); }
void write_uint(char *buf, unsigned int num, int offset) { - *(unsigned int*)(buf + offset) = num; + memcpy(buf+offset, &num, sizeof(unsigned int)); }
void write_float(char *buf, float num, int offset) { - *(float*)(buf + offset) = num; + memcpy(buf+offset, &num, sizeof(float)); }
void write_double(char *buf, double num, int offset) { - *(double*)(buf + offset) = num; + memcpy(buf+offset, &num, sizeof(double)); }
char *offset_charp(char *p, int offset) { @@ -172,6 +180,14 @@ return db->truncate(db, txnid, countp, flags); }
+int db_set_flags(DB *db, u_int32_t flags) { + return db->set_flags(db, flags); +} + +int db_get_flags(DB *db, u_int32_t *flagsp) { + return db->get_flags(db, flagsp); +} + int db_set_pagesize(DB *db, u_int32_t pagesize) { return db->set_pagesize(db, pagesize); } @@ -180,54 +196,303 @@ return db->get_pagesize(db, pagesizep); }
+int db_set_bt_compare(DB *db, + int (*bt_compare_fcn)(DB *db, const DBT *dbt1, + const DBT *dbt2)) { + return db->set_bt_compare(db, bt_compare_fcn); +} + +int db_set_dup_compare(DB *db, + int (*dup_compare_fcn)(DB *db, const DBT *dbt1, + const DBT *dbt2)) { + return db->set_dup_compare(db, dup_compare_fcn); +} + +#define type_numeric(c) ((c)<8) +#include <math.h> + +double read_num(char *buf); + +/* Inspired by the Sleepycat docs. We have to memcpy to + insure memory alignment. */ +int lisp_compare(DB *dbp, const DBT *a, const DBT *b) { + int difference; + double ddifference; + char *ad, *bd, at, bt; + ad = (char*)a->data; + bd = (char*)b->data; + + /* Compare OIDs. */ + difference = read_int(ad, 0) - read_int(bd, 0); + if (difference) return difference; + + /* Have a type tag? */ + if (a->size == 4) + if (b->size == 4) + return 0; + else + return -1; + else if (b->size == 4) + return 1; + + at = ad[4]; bt = bd[4]; + + /* Compare numerics. */ + if (type_numeric(at) && type_numeric(bt)) { + ddifference = read_num(ad+4) - read_num(bd+4); + if (ddifference > 0) return 1; + else if (ddifference < 0) return -1; + return 0; + } + + /* Compare types. */ + difference = at - bt; + if (difference) return difference; + + /* Same type! */ + switch (at) { + case 8: /* nil */ + return 0; + case 9: /* 8-bit symbol */ + case 10: /* 8-bit string */ + case 11: /* 8-bit pathname */ + return case_cmp(ad+9, read_int(ad, 5), bd+9, read_int(bd, 5)); + case 12: /* 16-bit symbol */ + case 13: /* 16-bit string */ + case 14: /* 16-bit pathname */ + return utf16_cmp(ad+9, read_int(ad, 5), bd+9, read_int(bd, 5)); + default: + return lex_cmp(ad+5, (a->size)-5, bd+5, (b->size)-5); + } +} + +int db_set_lisp_compare(DB *db) { + return db->set_bt_compare(db, &lisp_compare); +} + +int db_set_lisp_dup_compare(DB *db) { + return db->set_dup_compare(db, &lisp_compare); +} + +#ifndef exp2 +#define exp2(c) (pow(2,(c))) +#endif + +double read_num(char *buf) { + char *limit; + double i, result, denom; + switch (buf[0]) { + case 1: + case 2: + return (double)read_int(buf, 1); + case 3: + return (double)read_float(buf, 1); + case 4: + return read_double(buf, 1); + case 5: + result = 0; + buf += 5; + limit = buf + read_uint(buf, -4); + for(i=0 ; buf < limit; i++, buf = buf+4) { + result -= exp2(i*32) * read_uint(buf, 0); + } + return result; + case 6: + result = 0; + buf += 5; + limit = buf + read_uint(buf, -4); + for(i=0 ; buf < limit; i++, buf = buf+4) { + result += exp2(i*32) * read_uint(buf, 0); + } + return result; + case 7: + switch ((++buf)[0]) { + case 1: + result = (double)read_int(++buf, 0); + buf += 4; + break; + case 5: + result = 0; + buf += 5; + limit = buf + read_uint(buf, -4); + for(i=0 ; buf < limit; i++, buf = buf+4) { + result -= exp2(i*32) - read_uint(buf, 0); + } + break; + case 6: + result = 0; + buf += 5; + limit = buf + read_uint(buf, -4); + for(i=0 ; buf < limit; i++, buf = buf+4) { + result += exp2(i*32) * read_uint(buf, 0); + } + break; + } + + switch (buf[0]) { + case 1: + return result / read_int(++buf, 0); + case 5: + denom = 0; + buf += 5; + limit = buf + read_uint(buf, -4); + for(i=0 ; buf < limit; i++, buf = buf+4) { + denom -= exp2(i*32) * read_uint(buf, 0); + } + return result / denom; + case 6: + denom = 0; + buf += 5; + limit = buf + read_uint(buf, -4); + for(i=0 ; buf < limit; i++, buf = buf+4) { + denom += exp2(i*32) * read_uint(buf, 0); + } + return result / denom; + } + } +} + +int case_cmp(const char *a, int32_t length1, const char *b, int32_t length2) { + int min, sizediff, diff; + sizediff = length1 - length2; + min = sizediff > 0 ? length2 : length1; + diff = strncasecmp(a, b, min); + if (diff == 0) return sizediff; + return diff; +} + +int lex_cmp(const char *a, int32_t length1, const char *b, int32_t length2) { + int min, sizediff, diff; + sizediff = length1 - length2; + min = sizediff > 0 ? length2 : length1; + diff = memcmp(a, b, min); + if (diff == 0) return sizediff; + return diff; +} +/* The following is copied from + http://oss.software.ibm.com/cvs/icu/~checkout~/icu/source/common/ustring.c +*/ +typedef uint16_t UChar; + +#define UTF_IS_LEAD(c) (((c)&0xfffffc00)==0xd800) +#define UTF_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00) + +/* compare UTF-16 strings */ +/* memcmp/UnicodeString style, both length-specified */ +/* don't assume byte-aligned! */ +int utf16_cmp(const char *s1, int32_t length1, + const char *s2, int32_t length2) { + const char *start1, *start2, *limit1, *limit2; + UChar c1, c2; + int32_t lengthResult; + + if(length1<length2) { + lengthResult=-1; + limit1=s1+length1; + } else if(length1==length2) { + lengthResult=0; + limit1=s1+length1; + } else /* length1>length2 */ { + lengthResult=1; + limit1=s1+length2; + } + + if(s1==s2) return lengthResult; + + start1=s1; + start2=s2; + + for(;;) { + if(s1==limit1) return lengthResult; + + memcpy(&c1, s1, sizeof(UChar)); + memcpy(&c2, s2, sizeof(UChar)); + if(c1!=c2) break; + + s1 = s1 + 2; + s2 = s2 + 2; + } + + limit1=start1+length1; + limit2=start2+length2; + + if(c1>=0xd800 && c2>=0xd800) { + if(c1>=0xe000) + c1-=0x800; + else + c1+=0x2000; + + if(c2>=0xe000) + c2-=0x800; + else + c2+=0x2000; + + /* here's some newer code which i can't make work + if((c1<=0xdbff && (s1+1)!=limit1 && UTF_IS_TRAIL(*(s1+1))) || + (UTF_IS_TRAIL(c1) && start1!=s1 && UTF_IS_LEAD(*(s1-1)))) { + } else { + c1-=0x2800; + } + + if((c2<=0xdbff && (s2+1)!=limit2 && UTF_IS_TRAIL(*(s2+1))) || + (UTF_IS_TRAIL(c2) && start2!=s2 && UTF_IS_LEAD(*(s2-1)))) { + } else { + c2-=0x2800; + }*/ + } + + return (int32_t)c1-(int32_t)c2; +} + + /* Accessors */ /* We manage our own buffers (DB_DBT_USERMEM). */
int db_get_raw(DB *db, DB_TXN *txnid, - char *key, u_int32_t key_length, + char *key, u_int32_t key_size, char *buffer, u_int32_t buffer_length, - u_int32_t flags, u_int32_t *result_length) { - DBT DBTKey, DBTDatum; + u_int32_t flags, u_int32_t *result_size) { + DBT DBTKey, DBTValue; int ret;
memset(&DBTKey, 0, sizeof(DBT)); - memset(&DBTDatum, 0, sizeof(DBT)); + memset(&DBTValue, 0, sizeof(DBT)); DBTKey.data = key; - DBTKey.size = key_length; - DBTDatum.data = buffer; - DBTDatum.ulen = buffer_length; - DBTDatum.flags |= DB_DBT_USERMEM; + DBTKey.size = key_size; + DBTValue.data = buffer; + DBTValue.ulen = buffer_length; + DBTValue.flags |= DB_DBT_USERMEM;
- ret = db->get(db, txnid, &DBTKey, &DBTDatum, flags); - *result_length = DBTDatum.size; + ret = db->get(db, txnid, &DBTKey, &DBTValue, flags); + *result_size = DBTValue.size;
return ret; }
int db_put_raw(DB *db, DB_TXN *txnid, - char *key, u_int32_t key_length, - char *datum, u_int32_t datum_length, + char *key, u_int32_t key_size, + char *value, u_int32_t value_size, u_int32_t flags) { - DBT DBTKey, DBTDatum; + DBT DBTKey, DBTValue;
memset(&DBTKey, 0, sizeof(DBT)); - memset(&DBTDatum, 0, sizeof(DBT)); + memset(&DBTValue, 0, sizeof(DBT)); DBTKey.data = key; - DBTKey.size = key_length; - DBTDatum.data = datum; - DBTDatum.size = datum_length; + DBTKey.size = key_size; + DBTValue.data = value; + DBTValue.size = value_size;
- return db->put(db, txnid, &DBTKey, &DBTDatum, flags); + return db->put(db, txnid, &DBTKey, &DBTValue, flags); }
int db_del(DB *db, DB_TXN *txnid, - char *key, u_int32_t key_length, + char *key, u_int32_t key_size, u_int32_t flags) { DBT DBTKey;
memset(&DBTKey, 0, sizeof(DBT)); DBTKey.data = key; - DBTKey.size = key_length; + DBTKey.size = key_size; return db->del(db, txnid, &DBTKey, flags); }
@@ -255,72 +520,148 @@ }
int db_cursor_get_raw(DBC *cursor, - char *keybuf, u_int32_t keybuf_length, - char *buffer, u_int32_t buffer_length, - u_int32_t flags, u_int32_t *key_length, - u_int32_t *result_length) { - DBT DBTKey, DBTDatum; + char *keybuf, u_int32_t keybuf_size, + u_int32_t keybuf_length, + char *buffer, u_int32_t buffer_size, + u_int32_t buffer_length, + u_int32_t flags, u_int32_t *ret_key_size, + u_int32_t *result_size) { + DBT DBTKey, DBTValue; + int ret; + + memset(&DBTKey, 0, sizeof(DBT)); + memset(&DBTValue, 0, sizeof(DBT)); + DBTKey.data = keybuf; + DBTKey.size = keybuf_size; + DBTKey.ulen = keybuf_length; + DBTKey.flags |= DB_DBT_USERMEM; + DBTValue.data = buffer; + DBTValue.size = buffer_size; + DBTValue.ulen = buffer_length; + DBTValue.flags |= DB_DBT_USERMEM; + + ret = cursor->c_get(cursor, &DBTKey, &DBTValue, flags); + *ret_key_size = DBTKey.size; + *result_size = DBTValue.size; + + return ret; +} + +int db_cursor_pget_raw(DBC *cursor, + char *keybuf, u_int32_t keybuf_size, + u_int32_t keybuf_length, + char *pkeybuf, u_int32_t pkeybuf_size, + u_int32_t pkeybuf_length, + char *buffer, u_int32_t buffer_size, + u_int32_t buffer_length, + u_int32_t flags, + u_int32_t *ret_key_size, + u_int32_t *ret_pkey_size, + u_int32_t *result_size) { + DBT DBTKey, DBTPKey, DBTValue; int ret;
memset(&DBTKey, 0, sizeof(DBT)); - memset(&DBTDatum, 0, sizeof(DBT)); + memset(&DBTPKey, 0, sizeof(DBT)); + memset(&DBTValue, 0, sizeof(DBT)); DBTKey.data = keybuf; + DBTKey.size = keybuf_size; DBTKey.ulen = keybuf_length; DBTKey.flags |= DB_DBT_USERMEM; - DBTDatum.data = buffer; - DBTDatum.ulen = buffer_length; - DBTDatum.flags |= DB_DBT_USERMEM; - - ret = cursor->c_get(cursor, &DBTKey, &DBTDatum, flags); - *key_length = DBTKey.size; - *result_length = DBTDatum.size; + DBTPKey.data = pkeybuf; + DBTPKey.size = pkeybuf_size; + DBTPKey.ulen = pkeybuf_length; + DBTPKey.flags |= DB_DBT_USERMEM; + DBTValue.data = buffer; + DBTValue.size = buffer_size; + DBTValue.ulen = buffer_length; + DBTValue.flags |= DB_DBT_USERMEM; + + ret = cursor->c_pget(cursor, &DBTKey, &DBTPKey, &DBTValue, flags); + *ret_key_size = DBTKey.size; + *ret_pkey_size = DBTPKey.size; + *result_size = DBTValue.size;
return ret; }
int db_cursor_put_raw(DBC *cursor, - char *key, u_int32_t key_length, - char *datum, u_int32_t datum_length, + char *key, u_int32_t key_size, + char *value, u_int32_t value_size, u_int32_t flags) { - DBT DBTKey, DBTDatum; + DBT DBTKey, DBTValue;
memset(&DBTKey, 0, sizeof(DBT)); - memset(&DBTDatum, 0, sizeof(DBT)); + memset(&DBTValue, 0, sizeof(DBT)); DBTKey.data = key; - DBTKey.size = key_length; - DBTDatum.data = datum; - DBTDatum.size = datum_length; + DBTKey.size = key_size; + DBTValue.data = value; + DBTValue.size = value_size;
- return cursor->c_put(cursor, &DBTKey, &DBTDatum, flags); + return cursor->c_put(cursor, &DBTKey, &DBTValue, flags); }
+/* Silently does nothing if the key/value isn't found. + Can't use auto-commit here! */ +int db_del_kv(DB *db, DB_TXN *tid, + char *key, u_int32_t key_size, + char *value, u_int32_t value_size) { + DBT DBTKey, DBTValue; + DBC *cursor; + int ret, c_ret; + + memset(&DBTKey, 0, sizeof(DBT)); + DBTKey.data = key; + DBTKey.size = key_size; + memset(&DBTValue, 0, sizeof(DBT)); + DBTValue.data = value; + DBTValue.size = value_size; + + if ((ret = db->cursor(db, tid, &cursor, 0)) != 0) + return ret; + + if ((ret = cursor->c_get(cursor, &DBTKey, &DBTValue, DB_GET_BOTH)) != 0) + goto fail; + + ret = cursor->c_del(cursor, 0); + + fail: + if ((c_ret = cursor->c_close(cursor)) != 0) + return c_ret; + return ret; +} + /* Bulk retrieval */
int db_cursor_get_multiple_key(DBC *cursor, - char *keybuf, u_int32_t keybuf_length, - char *buffer, u_int32_t buffer_length, - u_int32_t flags, u_int32_t *key_length, - u_int32_t *result_length, + char *keybuf, u_int32_t keybuf_size, + u_int32_t keybuf_length, + char *buffer, u_int32_t buffer_size, + u_int32_t buffer_length, + u_int32_t flags, u_int32_t *ret_key_size, + u_int32_t *result_size, void **pointer, DBT **data) { - DBT DBTKey, DBTDatum; + DBT DBTKey, DBTValue; int ret;
memset(&DBTKey, 0, sizeof(DBT)); - memset(&DBTDatum, 0, sizeof(DBT)); + memset(&DBTValue, 0, sizeof(DBT)); DBTKey.data = keybuf; + DBTKey.size = keybuf_size; DBTKey.ulen = keybuf_length; DBTKey.flags |= DB_DBT_USERMEM; - DBTDatum.data = buffer; - DBTDatum.ulen = buffer_length; - DBTDatum.flags |= DB_DBT_USERMEM; + DBTValue.data = buffer; + DBTValue.size = buffer_size; + DBTValue.ulen = buffer_length; + DBTValue.flags |= DB_DBT_USERMEM;
flags |= DB_MULTIPLE_KEY; - ret = cursor->c_get(cursor, &DBTKey, &DBTDatum, flags); - *key_length = DBTKey.size; - *result_length = DBTDatum.size; - if ((DBTKey.size <= DBTKey.ulen) && (DBTDatum.size <= DBTDatum.ulen)) { - **data = DBTDatum; + ret = cursor->c_get(cursor, &DBTKey, &DBTValue, flags); + *ret_key_size = DBTKey.size; + *result_size = DBTValue.size; + if ((DBTKey.size <= DBTKey.ulen) && (DBTValue.size <= DBTValue.ulen)) { + **data = DBTValue; DB_MULTIPLE_INIT(*pointer, *data); } @@ -328,11 +669,11 @@ }
void db_multiple_key_next(void *pointer, DBT *data, - char **key, u_int32_t *key_length, - char **result, u_int32_t *result_length) { + char **key, u_int32_t *ret_key_size, + char **result, u_int32_t *result_size) { DB_MULTIPLE_KEY_NEXT(pointer, data, - *key, *key_length, - *result, *result_length); + *key, *ret_key_size, + *result, *result_size); }
/* Transactions */ @@ -373,12 +714,12 @@ }
int db_env_lock_get(DB_ENV *env, u_int32_t locker, - u_int32_t flags, char *object, u_int32_t object_length, + u_int32_t flags, char *object, u_int32_t object_size, const db_lockmode_t lock_mode, DB_LOCK *lock) { DBT DBTObject; memset(&DBTObject, 0, sizeof(DBT)); DBTObject.data = object; - DBTObject.size = object_length; + DBTObject.size = object_size;
return env->lock_get(env, locker, flags, &DBTObject, lock_mode, lock); } @@ -414,11 +755,28 @@ return env->lock_detect(env, flags, atype, aborted); }
+/* Secondary indices */ + +int db_associate(DB *primary, DB_TXN *txnid, DB *secondary, + int (*callback)(DB *, const DBT *, const DBT *, DBT *), + u_int32_t flags) { + return primary->associate(primary, txnid, secondary, callback, flags); +} + +int never_index(DB *db, const DBT *key, const DBT *data, DBT *result) { + return DB_DONOTINDEX; +} + +int db_fake_associate(DB *primary, DB_TXN *txnid, DB *secondary, + u_int32_t flags) { + return primary->associate(primary, txnid, secondary, &never_index, flags); +} + /* Poor man's counters */
int next_counter(DB_ENV *env, DB *db, DB_TXN *parent, - char *key, u_int32_t key_length, - char *lockid, u_int32_t lockid_length) { + char *key, u_int32_t key_size, + char *lockid, u_int32_t lockid_size) { DB_LOCK lock; DBT DBTKey, DBTData; DB_TXN *tid; @@ -430,9 +788,9 @@ memset(&DBTKey, 0, sizeof(DBTKey)); memset(&DBTData, 0, sizeof(DBTData)); DBTKey.data = key; - DBTKey.size = key_length; + DBTKey.size = key_size; DBTData.data = lockid; - DBTData.size = lockid_length; + DBTData.size = lockid_size;
tries = 0;