From ec55f05ca09085400d40b2d8b6b2c093b256f004 Mon Sep 17 00:00:00 2001 From: leitner Date: Mon, 25 Mar 2002 23:46:34 +0000 Subject: [PATCH] Initial index query support --- Makefile | 2 +- addindex.c | 5 +- tinyldap.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 215 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 0c7e3ab..dba5527 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ ldif.a: ldif_parse.o ldap_match.o ldap_match_mapped.o storage.a: strstorage.o strduptab.o mstorage_add.o mduptab_add.o -DIET=diet -Os +DIET=/opt/diet/bin/diet -Os CC=gcc CFLAGS=-pipe -I. -Wall -W ifneq ($(DEBUG),) diff --git a/addindex.c b/addindex.c index 0be1b34..7e6ff62 100644 --- a/addindex.c +++ b/addindex.c @@ -8,15 +8,16 @@ #include "mstorage.h" mstorage_t idx; +char* map; int compar(const void* a,const void* b) { - return *(uint32*)b - *(uint32*)a; + return strcmp(map+*(uint32*)a,map+*(uint32*)b); +// return *(uint32*)b - *(uint32*)a; } int main(int argc,char* argv[]) { long filelen; char* filename=argv[1]?argv[1]:"data"; - char* map; uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table; uint32 wanted,dn,objectClass; diff --git a/tinyldap.c b/tinyldap.c index 82fb5a4..8ea92b8 100644 --- a/tinyldap.c +++ b/tinyldap.c @@ -18,6 +18,9 @@ char* map; long filelen; uint32 magic,attribute_count,record_count,indices_offset,size_of_string_table; +/* how many longs are needed to have one bit for each record? */ +uint32 record_set_length; + #define BUFSIZE 8192 static int indexable(struct Filter* f) { @@ -53,7 +56,7 @@ static int indexable(struct Filter* f) { uint32_unpack(map+ofs+4,&next); uint32_unpack(map+ofs+8,&indexed_attribute); if (index_type==0) - if (matchstring(&f->ava.desc,map+indexed_attribute)) + if (!matchstring(&f->ava.desc,map+indexed_attribute)) return 1; ofs=next; } @@ -64,10 +67,6 @@ static int indexable(struct Filter* f) { } } -#define MAXINDEXMATCHES 100 -static uint32 matches[MAXINDEXMATCHES]; -static uint32 matchcounter; - /* find record given a data pointer */ static uint32 findrec(uint32 dat) { uint32* records=(uint32*)(map+indices_offset); @@ -78,17 +77,183 @@ static uint32 findrec(uint32 dat) { uint32 k,l; uint32_unpack(&records[mid],&k); uint32_unpack(map+k+8,&l); + +#if 0 + buffer_puts(buffer_2,"findrec: look for "); + buffer_putulong(buffer_2,dat); + buffer_puts(buffer_2," in record "); + buffer_putulong(buffer_2,mid); + buffer_puts(buffer_2," @"); + buffer_putulong(buffer_2,l); + buffer_putsflush(buffer_2,".\n"); +#endif + if (ldat) return k; /* found! */ + if (middat) return mid; /* found! */ bottom=mid+1; } else - top=mid-1; + if (mid) + top=mid-1; + else + break; } + buffer_putsflush(buffer_2,"findrec failed!\n"); return 0; } +static inline void emptyset(unsigned long* r) { + unsigned long i; + for (i=0; i0) + buffer_putsflush(buffer_2,"not properly sorted!\n"); + } + } + } +#endif + + while ((top>=bottom)) { + uint32 mid=(top+bottom)/2; + uint32 k; + int l; + +#if 0 + buffer_puts(buffer_2,"bottom="); + buffer_putulong(buffer_2,bottom); + buffer_puts(buffer_2,", mid="); + buffer_putulong(buffer_2,mid); + buffer_puts(buffer_2,", top="); + buffer_putulong(buffer_2,top); + buffer_puts(buffer_2,", elements="); + buffer_putulong(buffer_2,elements); + buffer_putsflush(buffer_2,".\n"); +#endif + + uint32_unpack(&index[mid],&k); + if ((l=matchstring(s,map+k))==0) { + /* match! */ + uint32 rec; + uint32 oldk=k; + if ((rec=findrec(k))) + setbit(bitfield,rec); + /* there may be multiple matches. + * Look before and after mid, too */ + for (oldk=k; k>0; ) { + k-=4; + if ((l=matchstring(s,map+k))==0) + if ((rec=findrec(k))) + setbit(bitfield,rec); + } + for (k=oldk; ks,s->l); + buffer_puts(buffer_2,"\" vs. \""); + buffer_puts(buffer_2,map+k); + buffer_puts(buffer_2," -> "); + buffer_putlong(buffer_2,l); + buffer_putsflush(buffer_2,"\n"); +#endif + + if (l<0) { + if (mid) + top=mid-1; + else + break; + } else + bottom=mid+1; + } +} + +static int useindex(struct Filter* f,unsigned long* bitfield) { + struct Filter* y=f->x; + if (!f) return 1; + switch (f->type) { + case AND: + while (y) { + if (!indexable(y)) return 0; + y=y->next; + } + return 1; + case OR: + while (y) { + if (!indexable(y)) return 0; + y=y->next; + } + return 1; +#if 0 + /* doesn't make much sense to try to speed up negated queries */ + case NOT: + return indexable(y); +#endif + case SUBSTRING: + if (f->substrings->substrtype!=prefix) return 0; + /* fall through */ + case EQUAL: + { + uint32 ofs; + for (ofs=indices_offset+record_count*4; ofs<(unsigned long)filelen;) { + uint32 index_type,next,indexed_attribute; + uint32_unpack(map+ofs,&index_type); + uint32_unpack(map+ofs+4,&next); + uint32_unpack(map+ofs+8,&indexed_attribute); + if (index_type==0) + if (!matchstring(&f->ava.desc,map+indexed_attribute)) { + tagmatches((uint32*)(map+ofs+12),(next-ofs-12)/4,&f->ava.value,bitfield); + return 1; + } + ofs=next; + } + } + /* fall through */ + default: + return 0; + } +} + static void answerwith(uint32 ofs,struct SearchRequest* sr,long messageid,int out) { uint32 k; struct SearchResultEntry sre; @@ -263,11 +428,36 @@ int handle(int in,int out) { #endif if ((tmp=scan_ldapsearchrequest(buf+res,buf+res+len,&sr))) { if (indexable(sr.filter)) { - buffer_putsflush(buffer_2,"query is indexable!\n"); + unsigned long* result; + unsigned long i; +// buffer_putsflush(buffer_2,"query is indexable!\n"); + record_set_length=(record_count+sizeof(unsigned long)*8-1) / (sizeof(long)*8); + result=alloca(record_set_length*sizeof(unsigned long)); /* Use the index to find matching data. Put the offsets * of the matches in a table. Use findrec to locate * the records that point to the data. */ - } /* else */ { + useindex(sr.filter,result); + for (i=0; i "); + { + uint32 l; + uint32_unpack(map+j+8,&l); + buffer_puts(buffer_2,map+l); + } + buffer_putsflush(buffer_2,"\n"); +#endif + + if (ldap_match_mapped(j,&sr)) + answerwith(j,&sr,messageid,out); + } + } else { char* x=map+5*4+size_of_string_table+attribute_count*8; unsigned long i; for (i=0; i